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

📄 zero.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		dev->config = number;		INFO (dev, "%s speed config #%d: %s\n", speed, number,				(number == CONFIG_SOURCE_SINK)					? source_sink : loopback);	}	return result;}/*-------------------------------------------------------------------------*/static void zero_setup_complete (struct usb_ep *ep, struct usb_request *req){	if (req->status || req->actual != req->length)		DBG ((struct zero_dev *) ep->driver_data,				"setup complete --> %d, %d/%d\n",				req->status, req->actual, req->length);}/* * The setup() callback implements all the ep0 functionality that's * not handled lower down, in hardware or the hardware driver (like * device and endpoint feature flags, and their status).  It's all * housekeeping for the gadget function we're implementing.  Most of * the work is in config-specific setup. */static intzero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl){	struct zero_dev		*dev = get_gadget_data (gadget);	struct usb_request	*req = dev->req;	int			value = -EOPNOTSUPP;	/* usually this stores reply data in the pre-allocated ep0 buffer,	 * but config change events will reconfigure hardware.	 */	switch (ctrl->bRequest) {	case USB_REQ_GET_DESCRIPTOR:		if (ctrl->bRequestType != USB_DIR_IN)			goto unknown;		switch (ctrl->wValue >> 8) {		case USB_DT_DEVICE:			value = min (ctrl->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 (ctrl->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, req->buf,					ctrl->wValue >> 8,					ctrl->wValue & 0xff);			if (value >= 0)				value = min (ctrl->wLength, (u16) value);			break;		case USB_DT_STRING:			/* wIndex == language code.			 * this driver only handles one language, you can			 * add others even if they don't use iso8859/1			 */			value = usb_gadget_get_string (&stringtab,					ctrl->wValue & 0xff, req->buf);			if (value >= 0)				value = min (ctrl->wLength, (u16) value);			break;		}		break;	/* currently two configs, two speeds */	case USB_REQ_SET_CONFIGURATION:		if (ctrl->bRequestType != 0)			goto unknown;		spin_lock (&dev->lock);		value = zero_set_config (dev, ctrl->wValue, GFP_ATOMIC);		spin_unlock (&dev->lock);		break;	case USB_REQ_GET_CONFIGURATION:		if (ctrl->bRequestType != USB_DIR_IN)			goto unknown;		*(u8 *)req->buf = dev->config;		value = min (ctrl->wLength, (u16) 1);		break;	/* until we add altsetting support, or other interfaces,	 * only 0/0 are possible.  pxa2xx only supports 0/0 (poorly)	 * and already killed pending endpoint I/O.	 */	case USB_REQ_SET_INTERFACE:		if (ctrl->bRequestType != USB_RECIP_INTERFACE)			goto unknown;		spin_lock (&dev->lock);		if (dev->config && ctrl->wIndex == 0 && ctrl->wValue == 0) {			u8		config = dev->config;			/* resets interface configuration, forgets about			 * previous transaction state (queued bufs, etc)			 * and re-inits endpoint state (toggle etc)			 * no response queued, just zero status == success.			 * if we had more than one interface we couldn't			 * use this "reset the config" shortcut.			 */			zero_reset_config (dev);			zero_set_config (dev, config, GFP_ATOMIC);			value = 0;		}		spin_unlock (&dev->lock);		break;	case USB_REQ_GET_INTERFACE:		if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))			goto unknown;		if (!dev->config)			break;		if (ctrl->wIndex != 0) {			value = -EDOM;			break;		}		*(u8 *)req->buf = 0;		value = min (ctrl->wLength, (u16) 1);		break;	/*	 * These are the same vendor-specific requests supported by	 * Intel's USB 2.0 compliance test devices.  We exceed that	 * device spec by allowing multiple-packet requests.	 */	case 0x5b:	/* control WRITE test -- fill the buffer */		if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))			goto unknown;		if (ctrl->wValue || ctrl->wIndex)			break;		/* just read that many bytes into the buffer */		if (ctrl->wLength > USB_BUFSIZ)			break;		value = ctrl->wLength;		break;	case 0x5c:	/* control READ test -- return the buffer */		if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))			goto unknown;		if (ctrl->wValue || ctrl->wIndex)			break;		/* expect those bytes are still in the buffer; send back */		if (ctrl->wLength > USB_BUFSIZ				|| ctrl->wLength != req->length)			break;		value = ctrl->wLength;		break;	default:unknown:		VDBG (dev,			"unknown control req%02x.%02x v%04x i%04x l%d\n",			ctrl->bRequestType, ctrl->bRequest,			ctrl->wValue, ctrl->wIndex, ctrl->wLength);	}	/* respond with data transfer before status phase? */	if (value >= 0) {		req->length = value;		value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);		if (value < 0) {			DBG (dev, "ep_queue --> %d\n", value);			req->status = 0;			zero_setup_complete (gadget->ep0, req);		}	}	/* device either stalls (value < 0) or reports success */	return value;}static voidzero_disconnect (struct usb_gadget *gadget){	struct zero_dev		*dev = get_gadget_data (gadget);	unsigned long		flags;	spin_lock_irqsave (&dev->lock, flags);	zero_reset_config (dev);	/* a more significant application might have some non-usb	 * activities to quiesce here, saving resources like power	 * or pushing the notification up a network stack.	 */	spin_unlock_irqrestore (&dev->lock, flags);	/* next we may get setup() calls to enumerate new connections;	 * or an unbind() during shutdown (including removing module).	 */}static voidzero_autoresume (unsigned long _dev){	struct zero_dev	*dev = (struct zero_dev *) _dev;	int		status;	/* normally the host would be woken up for something	 * more significant than just a timer firing...	 */	status = usb_gadget_wakeup (dev->gadget);	DBG (dev, "wakeup --> %d\n", status);}/*-------------------------------------------------------------------------*/static voidzero_unbind (struct usb_gadget *gadget){	struct zero_dev		*dev = get_gadget_data (gadget);	DBG (dev, "unbind\n");	/* we've already been disconnected ... no i/o is active */	if (dev->req)		free_ep_req (gadget->ep0, dev->req);	del_timer_sync (&dev->resume);	kfree (dev);	set_gadget_data (gadget, 0);}static intzero_bind (struct usb_gadget *gadget){	struct zero_dev		*dev;	struct usb_ep		*ep;	/* Bulk-only drivers like this one SHOULD be able to	 * autoconfigure on any sane usb controller driver,	 * but there may also be important quirks to address.	 */	usb_ep_autoconfig_reset (gadget);	ep = usb_ep_autoconfig (gadget, &fs_source_desc);	if (!ep) {autoconf_fail:		printk (KERN_ERR "%s: can't autoconfigure on %s\n",			shortname, gadget->name);		return -ENODEV;	}	EP_IN_NAME = ep->name;	ep->driver_data = ep;	/* claim */		ep = usb_ep_autoconfig (gadget, &fs_sink_desc);	if (!ep)		goto autoconf_fail;	EP_OUT_NAME = ep->name;	ep->driver_data = ep;	/* claim */	/*	 * DRIVER POLICY CHOICE:  you may want to do this differently.	 * One thing to avoid is reusing a bcdDevice revision code	 * with different host-visible configurations or behavior	 * restrictions -- using ep1in/ep2out vs ep1out/ep3in, etc	 */	if (gadget_is_net2280 (gadget)) {		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0201);	} else if (gadget_is_pxa (gadget)) {		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0203);#if 0	} else if (gadget_is_sh(gadget)) {		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0204);		/* SH has only one configuration; see "loopdefault" */		device_desc.bNumConfigurations = 1;		/* FIXME make 1 == default.bConfigurationValue */#endif	} else if (gadget_is_sa1100 (gadget)) {		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0205);	} else if (gadget_is_goku (gadget)) {		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0206);	} else if (gadget_is_mq11xx (gadget)) {		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207);	} else if (gadget_is_omap (gadget)) {		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208);	} else {		/* gadget zero is so simple (for now, no altsettings) that		 * it SHOULD NOT have problems with bulk-capable hardware.		 * so warn about unrcognized controllers, don't panic.		 *		 * things like configuration and altsetting numbering		 * can need hardware-specific attention though.		 */		printk (KERN_WARNING "%s: controller '%s' not recognized\n",			shortname, gadget->name);		device_desc.bcdDevice = __constant_cpu_to_le16 (0x9999);	}	/* ok, we made sense of the hardware ... */	dev = kmalloc (sizeof *dev, SLAB_KERNEL);	if (!dev)		return -ENOMEM;	memset (dev, 0, sizeof *dev);	spin_lock_init (&dev->lock);	dev->gadget = gadget;	set_gadget_data (gadget, dev);	/* preallocate control response and buffer */	dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);	if (!dev->req)		goto enomem;	dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,				&dev->req->dma, GFP_KERNEL);	if (!dev->req->buf)		goto enomem;	dev->req->complete = zero_setup_complete;	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;#ifdef CONFIG_USB_GADGET_DUALSPEED	/* assume ep0 uses the same value for both speeds ... */	dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;	/* and that all endpoints are dual-speed */	hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;	hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;#endif	usb_gadget_set_selfpowered (gadget);	init_timer (&dev->resume);	dev->resume.function = zero_autoresume;	dev->resume.data = (unsigned long) dev;	if (autoresume) {		source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;		loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;	}	gadget->ep0->driver_data = dev;	INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname);	INFO (dev, "using %s, OUT %s IN %s\n", gadget->name,		EP_OUT_NAME, EP_IN_NAME);	snprintf (manufacturer, sizeof manufacturer,		UTS_SYSNAME " " UTS_RELEASE " with %s",		gadget->name);	return 0;enomem:	zero_unbind (gadget);	return -ENOMEM;}/*-------------------------------------------------------------------------*/static voidzero_suspend (struct usb_gadget *gadget){	struct zero_dev		*dev = get_gadget_data (gadget);	if (gadget->speed == USB_SPEED_UNKNOWN)		return;	if (autoresume) {		mod_timer (&dev->resume, jiffies + (HZ * autoresume));		DBG (dev, "suspend, wakeup in %d seconds\n", autoresume);	} else		DBG (dev, "suspend\n");}static voidzero_resume (struct usb_gadget *gadget){	struct zero_dev		*dev = get_gadget_data (gadget);	DBG (dev, "resume\n");	del_timer (&dev->resume);}/*-------------------------------------------------------------------------*/static struct usb_gadget_driver zero_driver = {#ifdef CONFIG_USB_GADGET_DUALSPEED	.speed		= USB_SPEED_HIGH,#else	.speed		= USB_SPEED_FULL,#endif	.function	= (char *) longname,	.bind		= zero_bind,	.unbind		= zero_unbind,	.setup		= zero_setup,	.disconnect	= zero_disconnect,	.suspend	= zero_suspend,	.resume		= zero_resume,	.driver 	= {		.name		= (char *) shortname,		// .shutdown = ...		// .suspend = ...		// .resume = ...	},};MODULE_AUTHOR ("David Brownell");MODULE_LICENSE ("Dual BSD/GPL");static int __init init (void){	/* a real value would likely come through some id prom	 * or module option.  this one takes at least two packets.	 */	strlcpy (serial, "0123456789.0123456789.0123456789", sizeof serial);	return usb_gadget_register_driver (&zero_driver);}module_init (init);static void __exit cleanup (void){	usb_gadget_unregister_driver (&zero_driver);}module_exit (cleanup);

⌨️ 快捷键说明

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