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

📄 zero.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * zero.c -- Gadget Zero, for USB development * * Copyright (C) 2003-2004 David Brownell * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions, and the following disclaimer, *    without modification. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. The names of the above-listed copyright holders may not be used *    to endorse or promote products derived from this software without *    specific prior written permission. * * ALTERNATIVELY, this software may be distributed under the terms of the * GNU General Public License ("GPL") as published by the Free Software * Foundation, either version 2 of that License or (at your option) any * later version. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *//* * Gadget Zero only needs two bulk endpoints, and is an example of how you * can write a hardware-agnostic gadget driver running inside a USB device. * * Hardware details are visible (see CONFIG_USB_ZERO_* below) but don't * affect most of the driver. * * Use it with the Linux host/master side "usbtest" driver to get a basic * functional test of your device-side usb stack, or with "usb-skeleton". * * It supports two similar configurations.  One sinks whatever the usb host * writes, and in return sources zeroes.  The other loops whatever the host * writes back, so the host can read it.  Module options include: * *   buflen=N		default N=4096, buffer size used *   qlen=N		default N=32, how many buffers in the loopback queue *   loopdefault	default false, list loopback config first * * Many drivers will only have one configuration, letting them be much * simpler if they also don't support high speed operation (like this * driver does). */#define DEBUG 1// #define VERBOSE#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/ioport.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/smp_lock.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/timer.h>#include <linux/list.h>#include <linux/interrupt.h>#include <linux/utsname.h>#include <linux/device.h>#include <linux/moduleparam.h>#include <asm/byteorder.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/system.h>#include <asm/unaligned.h>#include <linux/usb_ch9.h>#include <linux/usb_gadget.h>#include "gadget_chips.h"/*-------------------------------------------------------------------------*/#define DRIVER_VERSION		"St Patrick's Day 2004"static const char shortname [] = "zero";static const char longname [] = "Gadget Zero";static const char source_sink [] = "source and sink data";static const char loopback [] = "loop input to output";/*-------------------------------------------------------------------------*//* * driver assumes self-powered hardware, and * has no way for users to trigger remote wakeup. * * this version autoconfigures as much as possible, * which is reasonable for most "bulk-only" drivers. */static const char *EP_IN_NAME;		/* source */static const char *EP_OUT_NAME;		/* sink *//*-------------------------------------------------------------------------*//* big enough to hold our biggest descriptor */#define USB_BUFSIZ	256struct zero_dev {	spinlock_t		lock;	struct usb_gadget	*gadget;	struct usb_request	*req;		/* for control responses */	/* when configured, we have one of two configs:	 * - source data (in to host) and sink it (out from host)	 * - or loop it back (out from host back in to host)	 */	u8			config;	struct usb_ep		*in_ep, *out_ep;	/* autoresume timer */	struct timer_list	resume;};#define xprintk(d,level,fmt,args...) \	dev_printk(level , &(d)->gadget->dev , fmt , ## args)#ifdef DEBUG#define DBG(dev,fmt,args...) \	xprintk(dev , KERN_DEBUG , fmt , ## args)#else#define DBG(dev,fmt,args...) \	do { } while (0)#endif /* DEBUG */#ifdef VERBOSE#define VDBG	DBG#else#define VDBG(dev,fmt,args...) \	do { } while (0)#endif /* VERBOSE */#define ERROR(dev,fmt,args...) \	xprintk(dev , KERN_ERR , fmt , ## args)#define WARN(dev,fmt,args...) \	xprintk(dev , KERN_WARNING , fmt , ## args)#define INFO(dev,fmt,args...) \	xprintk(dev , KERN_INFO , fmt , ## args)/*-------------------------------------------------------------------------*/static unsigned buflen = 4096;static unsigned qlen = 32;static unsigned pattern = 0;module_param (buflen, uint, S_IRUGO|S_IWUSR);module_param (qlen, uint, S_IRUGO|S_IWUSR);module_param (pattern, uint, S_IRUGO|S_IWUSR);/* * if it's nonzero, autoresume says how many seconds to wait * before trying to wake up the host after suspend. */static unsigned autoresume = 0;module_param (autoresume, uint, 0);/* * Normally the "loopback" configuration is second (index 1) so * it's not the default.  Here's where to change that order, to * work better with hosts where config changes are problematic. * Or controllers (like superh) that only support one config. */static int loopdefault = 0;module_param (loopdefault, bool, S_IRUGO|S_IWUSR);/*-------------------------------------------------------------------------*//* Thanks to NetChip Technologies for donating this product ID. * * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!! * Instead:  allocate your own, using normal USB-IF procedures. */#ifndef	CONFIG_USB_ZERO_HNPTEST#define DRIVER_VENDOR_NUM	0x0525		/* NetChip */#define DRIVER_PRODUCT_NUM	0xa4a0		/* Linux-USB "Gadget Zero" */#else#define DRIVER_VENDOR_NUM	0x1a0a		/* OTG test device IDs */#define DRIVER_PRODUCT_NUM	0xbadd#endif/*-------------------------------------------------------------------------*//* * DESCRIPTORS ... most are static, but strings and (full) * configuration descriptors are built on demand. */#define STRING_MANUFACTURER		25#define STRING_PRODUCT			42#define STRING_SERIAL			101#define STRING_SOURCE_SINK		250#define STRING_LOOPBACK			251/* * This device advertises two configurations; these numbers work * on a pxa250 as well as more flexible hardware. */#define	CONFIG_SOURCE_SINK	3#define	CONFIG_LOOPBACK		2static struct usb_device_descriptordevice_desc = {	.bLength =		sizeof device_desc,	.bDescriptorType =	USB_DT_DEVICE,	.bcdUSB =		__constant_cpu_to_le16 (0x0200),	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,	.idVendor =		__constant_cpu_to_le16 (DRIVER_VENDOR_NUM),	.idProduct =		__constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),	.iManufacturer =	STRING_MANUFACTURER,	.iProduct =		STRING_PRODUCT,	.iSerialNumber =	STRING_SERIAL,	.bNumConfigurations =	2,};static struct usb_config_descriptorsource_sink_config = {	.bLength =		sizeof source_sink_config,	.bDescriptorType =	USB_DT_CONFIG,	/* compute wTotalLength on the fly */	.bNumInterfaces =	1,	.bConfigurationValue =	CONFIG_SOURCE_SINK,	.iConfiguration =	STRING_SOURCE_SINK,	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,	.bMaxPower =		1,	/* self-powered */};static struct usb_config_descriptorloopback_config = {	.bLength =		sizeof loopback_config,	.bDescriptorType =	USB_DT_CONFIG,	/* compute wTotalLength on the fly */	.bNumInterfaces =	1,	.bConfigurationValue =	CONFIG_LOOPBACK,	.iConfiguration =	STRING_LOOPBACK,	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,	.bMaxPower =		1,	/* self-powered */};static struct usb_otg_descriptorotg_descriptor = {	.bLength =		sizeof otg_descriptor,	.bDescriptorType =	USB_DT_OTG,	.bmAttributes =		USB_OTG_SRP,};/* one interface in each configuration */static const struct usb_interface_descriptorsource_sink_intf = {	.bLength =		sizeof source_sink_intf,	.bDescriptorType =	USB_DT_INTERFACE,	.bNumEndpoints =	2,	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,	.iInterface =		STRING_SOURCE_SINK,};static const struct usb_interface_descriptorloopback_intf = {	.bLength =		sizeof loopback_intf,	.bDescriptorType =	USB_DT_INTERFACE,	.bNumEndpoints =	2,	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,	.iInterface =		STRING_LOOPBACK,};/* two full speed bulk endpoints; their use is config-dependent */static struct usb_endpoint_descriptorfs_source_desc = {	.bLength =		USB_DT_ENDPOINT_SIZE,	.bDescriptorType =	USB_DT_ENDPOINT,	.bEndpointAddress =	USB_DIR_IN,	.bmAttributes =		USB_ENDPOINT_XFER_BULK,};static struct usb_endpoint_descriptorfs_sink_desc = {	.bLength =		USB_DT_ENDPOINT_SIZE,	.bDescriptorType =	USB_DT_ENDPOINT,	.bEndpointAddress =	USB_DIR_OUT,	.bmAttributes =		USB_ENDPOINT_XFER_BULK,};static const struct usb_descriptor_header *fs_source_sink_function [] = {	(struct usb_descriptor_header *) &otg_descriptor,	(struct usb_descriptor_header *) &source_sink_intf,	(struct usb_descriptor_header *) &fs_sink_desc,	(struct usb_descriptor_header *) &fs_source_desc,	NULL,};static const struct usb_descriptor_header *fs_loopback_function [] = {	(struct usb_descriptor_header *) &otg_descriptor,	(struct usb_descriptor_header *) &loopback_intf,	(struct usb_descriptor_header *) &fs_sink_desc,	(struct usb_descriptor_header *) &fs_source_desc,	NULL,};#ifdef	CONFIG_USB_GADGET_DUALSPEED/* * usb 2.0 devices need to expose both high speed and full speed * descriptors, unless they only run at full speed. * * that means alternate endpoint descriptors (bigger packets) * and a "device qualifier" ... plus more construction options * for the config descriptor. */static struct usb_endpoint_descriptorhs_source_desc = {	.bLength =		USB_DT_ENDPOINT_SIZE,	.bDescriptorType =	USB_DT_ENDPOINT,	.bmAttributes =		USB_ENDPOINT_XFER_BULK,	.wMaxPacketSize =	__constant_cpu_to_le16 (512),};static struct usb_endpoint_descriptorhs_sink_desc = {	.bLength =		USB_DT_ENDPOINT_SIZE,	.bDescriptorType =	USB_DT_ENDPOINT,	.bmAttributes =		USB_ENDPOINT_XFER_BULK,	.wMaxPacketSize =	__constant_cpu_to_le16 (512),};static struct usb_qualifier_descriptordev_qualifier = {	.bLength =		sizeof dev_qualifier,	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,	.bcdUSB =		__constant_cpu_to_le16 (0x0200),	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,	.bNumConfigurations =	2,};static const struct usb_descriptor_header *hs_source_sink_function [] = {	(struct usb_descriptor_header *) &otg_descriptor,	(struct usb_descriptor_header *) &source_sink_intf,	(struct usb_descriptor_header *) &hs_source_desc,	(struct usb_descriptor_header *) &hs_sink_desc,	NULL,};static const struct usb_descriptor_header *hs_loopback_function [] = {	(struct usb_descriptor_header *) &otg_descriptor,	(struct usb_descriptor_header *) &loopback_intf,	(struct usb_descriptor_header *) &hs_source_desc,	(struct usb_descriptor_header *) &hs_sink_desc,	NULL,};/* maxpacket and other transfer characteristics vary by speed. */#define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))#else/* if there's no high speed support, maxpacket doesn't change. */#define ep_desc(g,hs,fs) fs#endif	/* !CONFIG_USB_GADGET_DUALSPEED */static char				manufacturer [50];static char				serial [40];/* static strings, in UTF-8 */static struct usb_string		strings [] = {	{ STRING_MANUFACTURER, manufacturer, },	{ STRING_PRODUCT, longname, },	{ STRING_SERIAL, serial, },	{ STRING_LOOPBACK, loopback, },	{ STRING_SOURCE_SINK, source_sink, },	{  }			/* end of list */};static struct usb_gadget_strings	stringtab = {	.language	= 0x0409,	/* en-us */	.strings	= strings,};/* * config descriptors are also handcrafted.  these must agree with code * that sets configurations, and with code managing interfaces and their * altsettings.  other complexity may come from: * *  - high speed support, including "other speed config" rules *  - multiple configurations *  - interfaces with alternate settings *  - embedded class or vendor-specific descriptors * * this handles high speed, and has a second config that could as easily * have been an alternate interface setting (on most hardware). * * NOTE:  to demonstrate (and test) more USB capabilities, this driver * should include an altsetting to test interrupt transfers, including * high bandwidth modes at high speed.  (Maybe work like Intel's test * device?) */static intconfig_buf (struct usb_gadget *gadget,		u8 *buf, u8 type, unsigned index){	int				is_source_sink;	int				len;	const struct usb_descriptor_header **function;#ifdef CONFIG_USB_GADGET_DUALSPEED	int				hs = (gadget->speed == USB_SPEED_HIGH);#endif	/* two configurations will always be index 0 and index 1 */

⌨️ 快捷键说明

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