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

📄 scanner.c

📁 Linux2.6系统下USB2.0gadget扫描仪驱动器
💻 C
📖 第 1 页 / 共 3 页
字号:
			DBG(dev, "Failed to dequeue in req %p\n",req);		list_del_init (&req->list);		list_add (&req->list, &dev->rx_reqs);	}		while (likely (!(list_empty (&dev->tx_reqs_active)))) {		req = container_of (dev->tx_reqs_active.next,				struct usb_request, list);		if (usb_ep_dequeue (dev->out_ep, req))			DBG(dev, "Failed to dequeue in req %p\n",req);		list_del_init (&req->list);		list_add (&req->list, &dev->tx_reqs);	}		if (usb_ep_enable (dev->in_ep, dev->in))		DBG(dev, "Failed to enable USB in_ep\n");	if (usb_ep_enable (dev->out_ep, dev->out))		DBG(dev, "Failed to enable USB out_ep\n");	wake_up_interruptible(&dev->tx_wait);	wake_up_interruptible(&dev->tx_flush_wait);}/*-------------------------------------------------------------------------*//* * The setup() callback implements all the ep0 functionality that's not * handled lower down. */static intprinter_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl){	struct printer_dev	*dev = get_gadget_data (gadget);	struct usb_request	*req = dev->req;	int			value = -EOPNOTSUPP;	u16			wIndex = le16_to_cpu(ctrl->wIndex);	u16			wValue = le16_to_cpu(ctrl->wValue);	u16			wLength = le16_to_cpu(ctrl->wLength);	DBG(dev, "ctrl req%02x.%02x v%04x i%04x l%d\n",		ctrl->bRequestType, ctrl->bRequest, wValue, wIndex, wLength);			req->complete = printer_setup_complete;	switch (ctrl->bRequestType&USB_TYPE_MASK) {	case USB_TYPE_STANDARD:		switch (ctrl->bRequest) {		case USB_REQ_GET_DESCRIPTOR:			if (ctrl->bRequestType != USB_DIR_IN)				break;			switch (wValue >> 8) {			case USB_DT_DEVICE:				value = min (wLength,						(u16) sizeof device_desc);				memcpy (req->buf, &device_desc, value);				break;#ifdef CONFIG_USB_GADGET_DUALSPEED			case USB_DT_DEVICE_QUALIFIER:				if (!gadget->is_dualspeed)					break;				value = min (wLength,						(u16) sizeof dev_qualifier);				memcpy (req->buf, &dev_qualifier, value);				break;			case USB_DT_OTHER_SPEED_CONFIG:				if (!gadget->is_dualspeed)					break;				// FALLTHROUGH#endif /* CONFIG_USB_GADGET_DUALSPEED */			case USB_DT_CONFIG:				value = config_buf (gadget->speed, req->buf,						wValue >> 8,						wValue & 0xff,						gadget->is_otg);				if (value >= 0)					value = min (wLength, (u16) value);				break;			case USB_DT_STRING:				value = usb_gadget_get_string (&stringtab,						wValue & 0xff, req->buf);				if (value >= 0)					value = min (wLength, (u16) value);				break;			}			break;		case USB_REQ_SET_CONFIGURATION:			if (ctrl->bRequestType != 0)				break;			if (gadget->a_hnp_support)				DBG(dev,"HNP available\n");			else if (gadget->a_alt_hnp_support)				DBG(dev,"HNP needs a different root port\n");			value = printer_set_config (dev, wValue);			break;		case USB_REQ_GET_CONFIGURATION:			if (ctrl->bRequestType != USB_DIR_IN)				break;			*(u8 *)req->buf = dev->config;			value = min (wLength, (u16) 1);			break;		case USB_REQ_SET_INTERFACE:			if (ctrl->bRequestType != USB_RECIP_INTERFACE ||					!dev->config)				break;			value = set_interface (dev, PRINTER_INTERFACE);			break;		case USB_REQ_GET_INTERFACE:			if (ctrl->bRequestType !=					(USB_DIR_IN|USB_RECIP_INTERFACE)					|| !dev->config)				break;			*(u8 *)req->buf = dev->interface;			value = min (wLength, (u16) 1);			break;		default:			VDBG(dev,				"unknown ctrl req%02x.%02x v%04x i%04x l%d\n",				ctrl->bRequestType, ctrl->bRequest,				wValue, wIndex, wLength);		}		break;	case USB_TYPE_CLASS:		switch (ctrl->bRequest) {		case 0: /* Get the IEEE-1284 PNP String */			/* Only one printer interface is supported. */			if ((wIndex>>8) != PRINTER_INTERFACE)				break;			//req->buf = pnp_string;			value = (pnp_string[0]<<8)|pnp_string[1];			memcpy(req->buf,pnp_string,value);			DBG(dev, "1284 PNP String: %x %s\n", value,					&pnp_string[2]);			break;					case 1: /* Get Port Status */			/* Only one printer interface is supported. */			if (wIndex != PRINTER_INTERFACE)				break;						req->buf = &dev->printer_status;			value = min (wLength, (u16) 1);			break;					case 2: /* Soft Reset */			/* Only one printer interface is supported. */			if (wIndex != PRINTER_INTERFACE)				break;			printer_soft_reset(dev);						value = 0;			break;					default:			VDBG(dev,				"unknown ctrl req%02x.%02x v%04x i%04x l%d\n",				ctrl->bRequestType, ctrl->bRequest,				wValue, wIndex, wLength);		}		break;			default:		VDBG(dev,			"unknown ctrl req%02x.%02x v%04x i%04x l%d\n",			ctrl->bRequestType, ctrl->bRequest,			wValue, wIndex, wLength);		break;	}	/* respond with data transfer before status phase? */	if (value >= 0) {		req->length = value;		req->zero = value < wLength				&& (value % gadget->ep0->maxpacket) == 0;		value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);		if (value < 0) {			DBG(dev, "ep_queue --> %d\n", value);			req->status = 0;			printer_setup_complete (gadget->ep0, req);		}	}	/* host either stalls (value < 0) or reports success */	return value;}static voidprinter_disconnect (struct usb_gadget *gadget){	struct printer_dev	*dev = get_gadget_data (gadget);	unsigned long		flags;	DBG(dev, "%s\n", __FUNCTION__);	spin_lock_irqsave (&dev->lock, flags);		printer_reset_interface (dev);	spin_unlock_irqrestore (&dev->lock, flags);}static voidprinter_unbind (struct usb_gadget *gadget){	struct printer_dev	*dev = get_gadget_data (gadget);	struct usb_request	*req;		DBG(dev, "%s\n", __FUNCTION__);	/* Remove sysfs files */	device_destroy(usb_gadget_class, g_printer_devno);	/* Remove Character Device */	cdev_del(&dev->printer_cdev);		/* we've already been disconnected ... no i/o is active */	/* Free all memory for this driver. */	while (likely (!list_empty (&dev->tx_reqs_active))) {		req = container_of (dev->tx_reqs_active.next,				struct usb_request, list);		list_del (&req->list);		if (usb_ep_dequeue (dev->in_ep, req)) {			DBG(dev, "Failed to dequeue in req %p\n",					req);		}		printer_req_free (dev->in_ep, req);	}	while (likely (!list_empty (&dev->tx_reqs))) {		req = container_of (dev->tx_reqs.next,				struct usb_request, list);		list_del (&req->list);		printer_req_free (dev->in_ep, req);	}	if (dev->current_rx_req) {		printer_req_free (dev->out_ep, dev->current_rx_req);	}	while (likely (!list_empty (&dev->rx_reqs_active))) {		req = container_of (dev->rx_reqs_active.next,				struct usb_request, list);		list_del (&req->list);		if (usb_ep_dequeue (dev->out_ep, req)) {			DBG(dev, "Failed to dequeue in req %p\n",					req);		}		printer_req_free (dev->out_ep, req);	}		while (likely (!list_empty (&dev->rx_reqs))) {		req = container_of (dev->rx_reqs.next,				struct usb_request, list);		list_del (&req->list);		printer_req_free (dev->out_ep, req);	}		while (likely (!list_empty (&dev->rx_buffers))) {		req = container_of (dev->rx_buffers.next,				struct usb_request, list);		list_del (&req->list);		printer_req_free (dev->out_ep, req);	}	if (dev->req) {		INFO (dev,"printer_req_free ep0=%p buf=%p\n", dev->req, dev->req_copy.buf);		kfree(dev->req_copy.buf);		//usb_ep_free_buffer (gadget->ep0, dev->req_copy.buf,		//		dev->req_copy.dma, dev->req_copy.length);		usb_ep_free_request (gadget->ep0, dev->req);		dev->req = NULL;	}		set_gadget_data (gadget, NULL);}static int __initprinter_bind (struct usb_gadget *gadget){	struct printer_dev	*dev;	u8			zlp = 1;	struct usb_ep		*in_ep, *out_ep;	int			status = -ENOMEM;	int			gcnum;	size_t			len;	u32			i;	struct usb_request	*req;	dev = &usb_printer_gadget;	/* Setup the sysfs files for the printer gadget. */	dev->pdev = device_create( usb_gadget_class, NULL, g_printer_devno,			"g_printer");	if (IS_ERR(dev->pdev)) {		ERROR (dev, "Failed to create device: g_printer\n");		goto fail;	}	/* 	 * Register a character device as an interface to a user mode	 * program that handles the printer specific functionality.	 */	cdev_init(&dev->printer_cdev, &printer_io_operations);	dev->printer_cdev.owner = THIS_MODULE;	status = cdev_add (&dev->printer_cdev, g_printer_devno, 1);	if (status) {		ERROR (dev, "Failed to open char device\n");		goto fail;	}	if (gadget_is_sa1100 (gadget)) {		/* hardware can't write zlps */		zlp = 0;	}	gcnum = usb_gadget_controller_number (gadget);	if (gcnum >= 0) {		device_desc.bcdDevice = cpu_to_le16 (0x0200 + gcnum);	} else {		dev_warn (&gadget->dev, "controller '%s' not recognized\n",			gadget->name);		/* unrecognized, but safe unless bulk is REALLY quirky */		device_desc.bcdDevice =			__constant_cpu_to_le16(0xFFFF);	}	snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s",		init_utsname()->sysname, init_utsname()->release,		gadget->name);	device_desc.idVendor =		__constant_cpu_to_le16(PRINTER_VENDOR_NUM);	device_desc.idProduct =		__constant_cpu_to_le16(PRINTER_PRODUCT_NUM);	/* support optional vendor/distro customization */	if (idVendor) {		if (!idProduct) {			dev_err (&gadget->dev, "idVendor needs idProduct!\n");			return -ENODEV;		}		device_desc.idVendor = cpu_to_le16(idVendor);		device_desc.idProduct = cpu_to_le16(idProduct);		if (bcdDevice)			device_desc.bcdDevice = cpu_to_le16(bcdDevice);	}	if (iManufacturer)		strlcpy (manufacturer, iManufacturer, sizeof manufacturer);	if (iProduct)		strlcpy (product_desc, iProduct, sizeof product_desc);	if (iSerialNum)		strlcpy (serial_num, iSerialNum, sizeof serial_num);	if (iPNPstring) {		strlcpy (&pnp_string[2], iPNPstring, (sizeof pnp_string)-2);	}	len = strlen (pnp_string);	pnp_string[0] = (len >> 8) & 0xFF;	pnp_string[1] = len & 0xFF;	/* all we really need is bulk IN/OUT */	usb_ep_autoconfig_reset (gadget);	in_ep = usb_ep_autoconfig (gadget, &fs_ep_in_desc);	if (!in_ep) {autoconf_fail:		dev_err (&gadget->dev,			"can't autoconfigure on %s\n",			gadget->name);		return -ENODEV;	}	in_ep->driver_data = in_ep;	/* claim */		out_ep = usb_ep_autoconfig (gadget, &fs_ep_out_desc);	if (!out_ep)		goto autoconf_fail;	out_ep->driver_data = out_ep;	/* claim */#ifdef	CONFIG_USB_GADGET_DUALSPEED	/* assumes ep0 uses the same value for both speeds ... */	dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;	/* and that all endpoints are dual-speed */	hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;	hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;#endif	/* DUALSPEED */	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;	usb_gadget_set_selfpowered (gadget);	if (gadget->is_otg) {		otg_desc.bmAttributes |= USB_OTG_HNP,		config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;		config_desc.bMaxPower = 4;	}	spin_lock_init (&dev->lock);	spin_lock_init (&dev->lock_printer_io);	INIT_LIST_HEAD (&dev->tx_reqs);	INIT_LIST_HEAD (&dev->tx_reqs_active);	INIT_LIST_HEAD (&dev->rx_reqs);		INIT_LIST_HEAD (&dev->rx_reqs_active);		INIT_LIST_HEAD (&dev->rx_buffers);		init_waitqueue_head(&dev->rx_wait);	init_waitqueue_head(&dev->tx_wait);	init_waitqueue_head(&dev->tx_flush_wait);	dev->config = 0;	dev->interface = -1;	dev->printer_cdev_open = 0;	dev->zlp = zlp;	dev->printer_status = PRINTER_NOT_ERROR;	dev->current_rx_req = NULL;	dev->current_rx_bytes = 0;	dev->current_rx_buf = NULL;	dev->in_ep = in_ep;	dev->out_ep = out_ep;	/* preallocate control message data and buffer */	dev->req = printer_req_alloc (gadget->ep0, USB_DESC_BUFSIZE,			GFP_KERNEL);	memcpy (&dev->req_copy, dev->req, sizeof dev->req_copy);	INFO (dev,"printer_req_free ep0=%p buf=%p\n", dev->req, dev->req->buf);	if (!dev->req) {		status = -ENOMEM;		goto fail;	}        for (i=0; i < QLEN; i++) {		req = printer_req_alloc (dev->in_ep, USB_BUFSIZE, GFP_KERNEL);                if (!req) {			while (likely (!list_empty (&dev->tx_reqs))) {				req = container_of (dev->tx_reqs.next,						struct usb_request, list);				list_del (&req->list);				printer_req_free (dev->in_ep, req);			}			return -ENOMEM;		}		list_add (&req->list, &dev->tx_reqs);	}        for (i=0; i < QLEN; i++) {		req = printer_req_alloc (dev->out_ep, USB_BUFSIZE, GFP_KERNEL);                if (!req) {			while (likely (!list_empty (&dev->rx_reqs))) {				req = container_of (dev->rx_reqs.next,						struct usb_request, list);				list_del (&req->list);				printer_req_free (dev->out_ep, req);			}			return -ENOMEM;		}		list_add (&req->list, &dev->rx_reqs);	}	dev->req->complete = printer_setup_complete;	/* finish hookup to lower layer ... */	dev->gadget = gadget;	set_gadget_data (gadget, dev);	gadget->ep0->driver_data = dev;	INFO (dev, "%s, version: " DRIVER_VERSION "\n", driver_desc);	INFO (dev, "using %s, OUT %s IN %s\n", gadget->name, out_ep->name,			in_ep->name);	return 0;fail:	printer_unbind (gadget);	return status;}static voidprinter_suspend (struct usb_gadget *gadget){	struct printer_dev	*dev = get_gadget_data (gadget);	DBG(dev, "suspend\n");	dev->suspended = 1;}static voidprinter_resume (struct usb_gadget *gadget){	struct printer_dev	*dev = get_gadget_data (gadget);	DBG(dev, "resume\n");	dev->suspended = 0;}/*-------------------------------------------------------------------------*/static struct usb_gadget_driver printer_driver = {	.speed		= DEVSPEED,	.function	= (char *) driver_desc,	.bind		= printer_bind,	.unbind		= printer_unbind,	.setup		= printer_setup,	.disconnect	= printer_disconnect,	.suspend	= printer_suspend,	.resume		= printer_resume,	.driver 	= {		.name		= (char *) shortname,		.owner		= THIS_MODULE,	},};MODULE_DESCRIPTION (DRIVER_DESC);MODULE_AUTHOR ("Craig Nadler, David Brownell");MODULE_LICENSE ("GPL");static int __init init (void){	int status;		usb_gadget_class = class_create(THIS_MODULE, "usb_gadget");	if (IS_ERR(usb_gadget_class)) {		status = PTR_ERR(usb_gadget_class);		ERROR (dev, "unable to create usb_gadget class %d\n", status);		return status;	}	status = alloc_chrdev_region (&g_printer_devno, 0, 2,			"USB printer gadget");	if (status) {		ERROR (dev, "alloc_chrdev_region %d\n", status);		class_destroy(usb_gadget_class);		return status;	}	status = usb_gadget_register_driver (&printer_driver);	if (status) {		class_destroy(usb_gadget_class);		unregister_chrdev_region (g_printer_devno, 2);		DBG(dev, "usb_gadget_register_driver %x\n", status);	}	return status;}module_init (init);static void __exit cleanup (void){	int status;	spin_lock (&usb_printer_gadget.lock_printer_io);	class_destroy(usb_gadget_class);	unregister_chrdev_region (g_printer_devno, 2);	status = usb_gadget_unregister_driver (&printer_driver);	if (status) {		ERROR (dev, "usb_gadget_unregister_driver %x\n", status);	}	spin_unlock (&usb_printer_gadget.lock_printer_io);}module_exit (cleanup);

⌨️ 快捷键说明

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