?? dummy_audio.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). */#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/uts.h>#include <linux/version.h>#include <linux/device.h>#include <linux/moduleparam.h>#include <linux/proc_fs.h>#include <asm/byteorder.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/system.h>#include <asm/unaligned.h>#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)# include <linux/usb/ch9.h>#else# include <linux/usb_ch9.h>#endif#include <linux/usb_gadget.h>/*-------------------------------------------------------------------------*//*-------------------------------------------------------------------------*/static int utf8_to_utf16le(const char *s, u16 *cp, unsigned len){ int count = 0; u8 c; u16 uchar; /* this insists on correct encodings, though not minimal ones. * BUT it currently rejects legit 4-byte UTF-8 code points, * which need surrogate pairs. (Unicode 3.1 can use them.) */ while (len != 0 && (c = (u8) *s++) != 0) { if (unlikely(c & 0x80)) { // 2-byte sequence: // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx if ((c & 0xe0) == 0xc0) { uchar = (c & 0x1f) << 6; c = (u8) *s++; if ((c & 0xc0) != 0xc0) goto fail; c &= 0x3f; uchar |= c; // 3-byte sequence (most CJKV characters): // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx } else if ((c & 0xf0) == 0xe0) { uchar = (c & 0x0f) << 12; c = (u8) *s++; if ((c & 0xc0) != 0xc0) goto fail; c &= 0x3f; uchar |= c << 6; c = (u8) *s++; if ((c & 0xc0) != 0xc0) goto fail; c &= 0x3f; uchar |= c; /* no bogus surrogates */ if (0xd800 <= uchar && uchar <= 0xdfff) goto fail; // 4-byte sequence (surrogate pairs, currently rare): // 11101110wwwwzzzzyy + 110111yyyyxxxxxx // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx // (uuuuu = wwww + 1) // FIXME accept the surrogate code points (only) } else goto fail; } else uchar = c; put_unaligned (cpu_to_le16 (uchar), cp++); count++; len--; } return count;fail: return -1;}/** * usb_gadget_get_string - fill out a string descriptor * @table: of c strings encoded using UTF-8 * @id: string id, from low byte of wValue in get string descriptor * @buf: at least 256 bytes * * Finds the UTF-8 string matching the ID, and converts it into a * string descriptor in utf16-le. * Returns length of descriptor (always even) or negative errno * * If your driver needs stings in multiple languages, you'll probably * "switch (wIndex) { ... }" in your ep0 string descriptor logic, * using this routine after choosing which set of UTF-8 strings to use. * Note that US-ASCII is a strict subset of UTF-8; any string bytes with * the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1 * characters (which are also widely used in C strings). */intusb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf){ struct usb_string *s; int len; /* descriptor 0 has the language id */ if (id == 0) { buf [0] = 4; buf [1] = USB_DT_STRING; buf [2] = (u8) table->language; buf [3] = (u8) (table->language >> 8); return 4; } for (s = table->strings; s && s->s; s++) if (s->id == id) break; /* unrecognized: stall. */ if (!s || !s->s) return -EINVAL; /* string descriptors have length, tag, then UTF16-LE text */ len = min ((size_t) 126, strlen (s->s)); memset (buf + 2, 0, 2 * len); /* zero all the bytes */ len = utf8_to_utf16le(s->s, (u16 *)&buf[2], len); if (len < 0) return -EINVAL; buf [0] = (len + 1) * 2; buf [1] = USB_DT_STRING; return buf [0];}/*-------------------------------------------------------------------------*//*-------------------------------------------------------------------------*//** * usb_descriptor_fillbuf - fill buffer with descriptors * @buf: Buffer to be filled * @buflen: Size of buf * @src: Array of descriptor pointers, terminated by null pointer. * * Copies descriptors into the buffer, returning the length or a * negative error code if they can't all be copied. Useful when * assembling descriptors for an associated set of interfaces used * as part of configuring a composite device; or in other cases where * sets of descriptors need to be marshaled. */intusb_descriptor_fillbuf(void *buf, unsigned buflen, const struct usb_descriptor_header **src){ u8 *dest = buf; if (!src) return -EINVAL; /* fill buffer from src[] until null descriptor ptr */ for (; 0 != *src; src++) { unsigned len = (*src)->bLength; if (len > buflen) return -EINVAL; memcpy(dest, *src, len); buflen -= len; dest += len; } return dest - (u8 *)buf;}/** * usb_gadget_config_buf - builts a complete configuration descriptor * @config: Header for the descriptor, including characteristics such * as power requirements and number of interfaces. * @desc: Null-terminated vector of pointers to the descriptors (interface, * endpoint, etc) defining all functions in this device configuration. * @buf: Buffer for the resulting configuration descriptor. * @length: Length of buffer. If this is not big enough to hold the * entire configuration descriptor, an error code will be returned. * * This copies descriptors into the response buffer, building a descriptor * for that configuration. It returns the buffer length or a negative * status code. The config.wTotalLength field is set to match the length * of the result, but other descriptor fields (including power usage and * interface count) must be set by the caller. * * Gadget drivers could use this when constructing a config descriptor * in response to USB_REQ_GET_DESCRIPTOR. They will need to patch the * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed. */int usb_gadget_config_buf( const struct usb_config_descriptor *config, void *buf, unsigned length, const struct usb_descriptor_header **desc){ struct usb_config_descriptor *cp = buf; int len; /* config descriptor first */ if (length < USB_DT_CONFIG_SIZE || !desc) return -EINVAL; *cp = *config; /* then interface/endpoint/class/vendor/... */ len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf, length - USB_DT_CONFIG_SIZE, desc); if (len < 0) return len; len += USB_DT_CONFIG_SIZE; if (len > 0xffff) return -EINVAL; /* patch up the config descriptor */ cp->bLength = USB_DT_CONFIG_SIZE; cp->bDescriptorType = USB_DT_CONFIG; cp->wTotalLength = cpu_to_le16(len); cp->bmAttributes |= USB_CONFIG_ATT_ONE; return len;}/*-------------------------------------------------------------------------*//*-------------------------------------------------------------------------*/#define RBUF_LEN (1024*1024)static int rbuf_start;static int rbuf_len;static __u8 rbuf[RBUF_LEN];/*-------------------------------------------------------------------------*/#define DRIVER_VERSION "St Patrick's Day 2004"static const char shortname [] = "zero";static const char longname [] = "YAMAHA YST-MS35D USB Speaker ";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 512struct 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_MANUFACTURER 1#define STRING_PRODUCT 2#define STRING_SERIAL 3#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 2/*static 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_device_descriptordevice_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, .bcdUSB = __constant_cpu_to_le16 (0x0100), .bDeviceClass = USB_CLASS_PER_INTERFACE, .bDeviceSubClass = 0, .bDeviceProtocol = 0, .bMaxPacketSize0 = 64, .bcdDevice = __constant_cpu_to_le16 (0x0100), .idVendor = __constant_cpu_to_le16 (0x0499), .idProduct = __constant_cpu_to_le16 (0x3002), .iManufacturer = STRING_MANUFACTURER, .iProduct = STRING_PRODUCT, .iSerialNumber = STRING_SERIAL, .bNumConfigurations = 1,};static struct usb_config_descriptorz_config = { .bLength = sizeof z_config, .bDescriptorType = USB_DT_CONFIG, /* compute wTotalLength on the fly */ .bNumInterfaces = 2, .bConfigurationValue = 1, .iConfiguration = 0, .bmAttributes = 0x40, .bMaxPower = 0, /* 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 */#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_qualifier_descriptordev_qualifier = { .bLength = sizeof dev_qualifier, .bDescriptorType = USB_DT_DEVICE_QUALIFIER, .bcdUSB = __constant_cpu_to_le16 (0x0200), .bDeviceClass = USB_CLASS_VENDOR_SPEC,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -