?? zero.c
字號:
/* * 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 */ if (index > 1) return -EINVAL; is_source_sink = loopdefault ? (index == 1) : (index == 0);#ifdef CONFIG_USB_GADGET_DUALSPEED if (type == USB_DT_OTHER_SPEED_CONFIG)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -