aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/file_storage.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/file_storage.c')
-rw-r--r--drivers/usb/gadget/file_storage.c3656
1 files changed, 0 insertions, 3656 deletions
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
deleted file mode 100644
index 3f7d640b675..00000000000
--- a/drivers/usb/gadget/file_storage.c
+++ /dev/null
@@ -1,3656 +0,0 @@
-/*
- * file_storage.c -- File-backed USB Storage Gadget, for USB development
- *
- * Copyright (C) 2003-2008 Alan Stern
- * 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.
- */
-
-
-/*
- * The File-backed Storage Gadget acts as a USB Mass Storage device,
- * appearing to the host as a disk drive or as a CD-ROM drive. In addition
- * to providing an example of a genuinely useful gadget driver for a USB
- * device, it also illustrates a technique of double-buffering for increased
- * throughput. Last but not least, it gives an easy way to probe the
- * behavior of the Mass Storage drivers in a USB host.
- *
- * Backing storage is provided by a regular file or a block device, specified
- * by the "file" module parameter. Access can be limited to read-only by
- * setting the optional "ro" module parameter. (For CD-ROM emulation,
- * access is always read-only.) The gadget will indicate that it has
- * removable media if the optional "removable" module parameter is set.
- *
- * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI),
- * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected
- * by the optional "transport" module parameter. It also supports the
- * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03),
- * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by
- * the optional "protocol" module parameter. In addition, the default
- * Vendor ID, Product ID, release number and serial number can be overridden.
- *
- * There is support for multiple logical units (LUNs), each of which has
- * its own backing file. The number of LUNs can be set using the optional
- * "luns" module parameter (anywhere from 1 to 8), and the corresponding
- * files are specified using comma-separated lists for "file" and "ro".
- * The default number of LUNs is taken from the number of "file" elements;
- * it is 1 if "file" is not given. If "removable" is not set then a backing
- * file must be specified for each LUN. If it is set, then an unspecified
- * or empty backing filename means the LUN's medium is not loaded. Ideally
- * each LUN would be settable independently as a disk drive or a CD-ROM
- * drive, but currently all LUNs have to be the same type. The CD-ROM
- * emulation includes a single data track and no audio tracks; hence there
- * need be only one backing file per LUN.
- *
- * Requirements are modest; only a bulk-in and a bulk-out endpoint are
- * needed (an interrupt-out endpoint is also needed for CBI). The memory
- * requirement amounts to two 16K buffers, size configurable by a parameter.
- * Support is included for both full-speed and high-speed operation.
- *
- * Note that the driver is slightly non-portable in that it assumes a
- * single memory/DMA buffer will be useable for bulk-in, bulk-out, and
- * interrupt-in endpoints. With most device controllers this isn't an
- * issue, but there may be some with hardware restrictions that prevent
- * a buffer from being used by more than one endpoint.
- *
- * Module options:
- *
- * file=filename[,filename...]
- * Required if "removable" is not set, names of
- * the files or block devices used for
- * backing storage
- * serial=HHHH... Required serial number (string of hex chars)
- * ro=b[,b...] Default false, booleans for read-only access
- * removable Default false, boolean for removable media
- * luns=N Default N = number of filenames, number of
- * LUNs to support
- * nofua=b[,b...] Default false, booleans for ignore FUA flag
- * in SCSI WRITE(10,12) commands
- * stall Default determined according to the type of
- * USB device controller (usually true),
- * boolean to permit the driver to halt
- * bulk endpoints
- * cdrom Default false, boolean for whether to emulate
- * a CD-ROM drive
- * transport=XXX Default BBB, transport name (CB, CBI, or BBB)
- * protocol=YYY Default SCSI, protocol name (RBC, 8020 or
- * ATAPI, QIC, UFI, 8070, or SCSI;
- * also 1 - 6)
- * vendor=0xVVVV Default 0x0525 (NetChip), USB Vendor ID
- * product=0xPPPP Default 0xa4a5 (FSG), USB Product ID
- * release=0xRRRR Override the USB release number (bcdDevice)
- * buflen=N Default N=16384, buffer size used (will be
- * rounded down to a multiple of
- * PAGE_CACHE_SIZE)
- *
- * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "serial", "ro",
- * "removable", "luns", "nofua", "stall", and "cdrom" options are available;
- * default values are used for everything else.
- *
- * The pathnames of the backing files and the ro settings are available in
- * the attribute files "file", "nofua", and "ro" in the lun<n> subdirectory of
- * the gadget's sysfs directory. If the "removable" option is set, writing to
- * these files will simulate ejecting/loading the medium (writing an empty
- * line means eject) and adjusting a write-enable tab. Changes to the ro
- * setting are not allowed when the medium is loaded or if CD-ROM emulation
- * is being used.
- *
- * This gadget driver is heavily based on "Gadget Zero" by David Brownell.
- * The driver's SCSI command interface was based on the "Information
- * technology - Small Computer System Interface - 2" document from
- * X3T9.2 Project 375D, Revision 10L, 7-SEP-93, available at
- * <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>. The single exception
- * is opcode 0x23 (READ FORMAT CAPACITIES), which was based on the
- * "Universal Serial Bus Mass Storage Class UFI Command Specification"
- * document, Revision 1.0, December 14, 1998, available at
- * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>.
- */
-
-
-/*
- * Driver Design
- *
- * The FSG driver is fairly straightforward. There is a main kernel
- * thread that handles most of the work. Interrupt routines field
- * callbacks from the controller driver: bulk- and interrupt-request
- * completion notifications, endpoint-0 events, and disconnect events.
- * Completion events are passed to the main thread by wakeup calls. Many
- * ep0 requests are handled at interrupt time, but SetInterface,
- * SetConfiguration, and device reset requests are forwarded to the
- * thread in the form of "exceptions" using SIGUSR1 signals (since they
- * should interrupt any ongoing file I/O operations).
- *
- * The thread's main routine implements the standard command/data/status
- * parts of a SCSI interaction. It and its subroutines are full of tests
- * for pending signals/exceptions -- all this polling is necessary since
- * the kernel has no setjmp/longjmp equivalents. (Maybe this is an
- * indication that the driver really wants to be running in userspace.)
- * An important point is that so long as the thread is alive it keeps an
- * open reference to the backing file. This will prevent unmounting
- * the backing file's underlying filesystem and could cause problems
- * during system shutdown, for example. To prevent such problems, the
- * thread catches INT, TERM, and KILL signals and converts them into
- * an EXIT exception.
- *
- * In normal operation the main thread is started during the gadget's
- * fsg_bind() callback and stopped during fsg_unbind(). But it can also
- * exit when it receives a signal, and there's no point leaving the
- * gadget running when the thread is dead. So just before the thread
- * exits, it deregisters the gadget driver. This makes things a little
- * tricky: The driver is deregistered at two places, and the exiting
- * thread can indirectly call fsg_unbind() which in turn can tell the
- * thread to exit. The first problem is resolved through the use of the
- * REGISTERED atomic bitflag; the driver will only be deregistered once.
- * The second problem is resolved by having fsg_unbind() check
- * fsg->state; it won't try to stop the thread if the state is already
- * FSG_STATE_TERMINATED.
- *
- * To provide maximum throughput, the driver uses a circular pipeline of
- * buffer heads (struct fsg_buffhd). In principle the pipeline can be
- * arbitrarily long; in practice the benefits don't justify having more
- * than 2 stages (i.e., double buffering). But it helps to think of the
- * pipeline as being a long one. Each buffer head contains a bulk-in and
- * a bulk-out request pointer (since the buffer can be used for both
- * output and input -- directions always are given from the host's
- * point of view) as well as a pointer to the buffer and various state
- * variables.
- *
- * Use of the pipeline follows a simple protocol. There is a variable
- * (fsg->next_buffhd_to_fill) that points to the next buffer head to use.
- * At any time that buffer head may still be in use from an earlier
- * request, so each buffer head has a state variable indicating whether
- * it is EMPTY, FULL, or BUSY. Typical use involves waiting for the
- * buffer head to be EMPTY, filling the buffer either by file I/O or by
- * USB I/O (during which the buffer head is BUSY), and marking the buffer
- * head FULL when the I/O is complete. Then the buffer will be emptied
- * (again possibly by USB I/O, during which it is marked BUSY) and
- * finally marked EMPTY again (possibly by a completion routine).
- *
- * A module parameter tells the driver to avoid stalling the bulk
- * endpoints wherever the transport specification allows. This is
- * necessary for some UDCs like the SuperH, which cannot reliably clear a
- * halt on a bulk endpoint. However, under certain circumstances the
- * Bulk-only specification requires a stall. In such cases the driver
- * will halt the endpoint and set a flag indicating that it should clear
- * the halt in software during the next device reset. Hopefully this
- * will permit everything to work correctly. Furthermore, although the
- * specification allows the bulk-out endpoint to halt when the host sends
- * too much data, implementing this would cause an unavoidable race.
- * The driver will always use the "no-stall" approach for OUT transfers.
- *
- * One subtle point concerns sending status-stage responses for ep0
- * requests. Some of these requests, such as device reset, can involve
- * interrupting an ongoing file I/O operation, which might take an
- * arbitrarily long time. During that delay the host might give up on
- * the original ep0 request and issue a new one. When that happens the
- * driver should not notify the host about completion of the original
- * request, as the host will no longer be waiting for it. So the driver
- * assigns to each ep0 request a unique tag, and it keeps track of the
- * tag value of the request associated with a long-running exception
- * (device-reset, interface-change, or configuration-change). When the
- * exception handler is finished, the status-stage response is submitted
- * only if the current ep0 request tag is equal to the exception request
- * tag. Thus only the most recently received ep0 request will get a
- * status-stage response.
- *
- * Warning: This driver source file is too long. It ought to be split up
- * into a header file plus about 3 separate .c files, to handle the details
- * of the Gadget, USB Mass Storage, and SCSI protocols.
- */
-
-
-/* #define VERBOSE_DEBUG */
-/* #define DUMP_MSGS */
-
-
-#include <linux/blkdev.h>
-#include <linux/completion.h>
-#include <linux/dcache.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/fcntl.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/kref.h>
-#include <linux/kthread.h>
-#include <linux/limits.h>
-#include <linux/module.h>
-#include <linux/rwsem.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/freezer.h>
-#include <linux/utsname.h>
-
-#include <linux/usb/composite.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-#include "gadget_chips.h"
-
-#define DRIVER_DESC "File-backed Storage Gadget"
-#define DRIVER_NAME "g_file_storage"
-#define DRIVER_VERSION "1 September 2010"
-
-static char fsg_string_manufacturer[64];
-static const char fsg_string_product[] = DRIVER_DESC;
-static const char fsg_string_config[] = "Self-powered";
-static const char fsg_string_interface[] = "Mass Storage";
-
-
-#include "storage_common.c"
-
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Alan Stern");
-MODULE_LICENSE("Dual BSD/GPL");
-
-/*
- * This driver assumes self-powered hardware and has no way for users to
- * trigger remote wakeup. It uses autoconfiguration to select endpoints
- * and endpoint addresses.
- */
-
-
-/*-------------------------------------------------------------------------*/
-
-
-/* Encapsulate the module parameter settings */
-
-static struct {
- char *file[FSG_MAX_LUNS];
- char *serial;
- bool ro[FSG_MAX_LUNS];
- bool nofua[FSG_MAX_LUNS];
- unsigned int num_filenames;
- unsigned int num_ros;
- unsigned int num_nofuas;
- unsigned int nluns;
-
- bool removable;
- bool can_stall;
- bool cdrom;
-
- char *transport_parm;
- char *protocol_parm;
- unsigned short vendor;
- unsigned short product;
- unsigned short release;
- unsigned int buflen;
-
- int transport_type;
- char *transport_name;
- int protocol_type;
- char *protocol_name;
-
-} mod_data = { // Default values
- .transport_parm = "BBB",
- .protocol_parm = "SCSI",
- .removable = 0,
- .can_stall = 1,
- .cdrom = 0,
- .vendor = FSG_VENDOR_ID,
- .product = FSG_PRODUCT_ID,
- .release = 0xffff, // Use controller chip type
- .buflen = 16384,
- };
-
-
-module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames,
- S_IRUGO);
-MODULE_PARM_DESC(file, "names of backing files or devices");
-
-module_param_named(serial, mod_data.serial, charp, S_IRUGO);
-MODULE_PARM_DESC(serial, "USB serial number");
-
-module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
-MODULE_PARM_DESC(ro, "true to force read-only");
-
-module_param_array_named(nofua, mod_data.nofua, bool, &mod_data.num_nofuas,
- S_IRUGO);
-MODULE_PARM_DESC(nofua, "true to ignore SCSI WRITE(10,12) FUA bit");
-
-module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
-MODULE_PARM_DESC(luns, "number of LUNs");
-
-module_param_named(removable, mod_data.removable, bool, S_IRUGO);
-MODULE_PARM_DESC(removable, "true to simulate removable media");
-
-module_param_named(stall, mod_data.can_stall, bool, S_IRUGO);
-MODULE_PARM_DESC(stall, "false to prevent bulk stalls");
-
-module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO);
-MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk");
-
-/* In the non-TEST version, only the module parameters listed above
- * are available. */
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-
-module_param_named(transport, mod_data.transport_parm, charp, S_IRUGO);
-MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)");
-
-module_param_named(protocol, mod_data.protocol_parm, charp, S_IRUGO);
-MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, "
- "8070, or SCSI)");
-
-module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO);
-MODULE_PARM_DESC(vendor, "USB Vendor ID");
-
-module_param_named(product, mod_data.product, ushort, S_IRUGO);
-MODULE_PARM_DESC(product, "USB Product ID");
-
-module_param_named(release, mod_data.release, ushort, S_IRUGO);
-MODULE_PARM_DESC(release, "USB release number");
-
-module_param_named(buflen, mod_data.buflen, uint, S_IRUGO);
-MODULE_PARM_DESC(buflen, "I/O buffer size");
-
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
-
-/*
- * These definitions will permit the compiler to avoid generating code for
- * parts of the driver that aren't used in the non-TEST version. Even gcc
- * can recognize when a test of a constant expression yields a dead code
- * path.
- */
-
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-
-#define transport_is_bbb() (mod_data.transport_type == USB_PR_BULK)
-#define transport_is_cbi() (mod_data.transport_type == USB_PR_CBI)
-#define protocol_is_scsi() (mod_data.protocol_type == USB_SC_SCSI)
-
-#else
-
-#define transport_is_bbb() 1
-#define transport_is_cbi() 0
-#define protocol_is_scsi() 1
-
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
-
-/*-------------------------------------------------------------------------*/
-
-
-struct fsg_dev {
- /* lock protects: state, all the req_busy's, and cbbuf_cmnd */
- spinlock_t lock;
- struct usb_gadget *gadget;
-
- /* filesem protects: backing files in use */
- struct rw_semaphore filesem;
-
- /* reference counting: wait until all LUNs are released */
- struct kref ref;
-
- struct usb_ep *ep0; // Handy copy of gadget->ep0
- struct usb_request *ep0req; // For control responses
- unsigned int ep0_req_tag;
- const char *ep0req_name;
-
- struct usb_request *intreq; // For interrupt responses
- int intreq_busy;
- struct fsg_buffhd *intr_buffhd;
-
- unsigned int bulk_out_maxpacket;
- enum fsg_state state; // For exception handling
- unsigned int exception_req_tag;
-
- u8 config, new_config;
-
- unsigned int running : 1;
- unsigned int bulk_in_enabled : 1;
- unsigned int bulk_out_enabled : 1;
- unsigned int intr_in_enabled : 1;
- unsigned int phase_error : 1;
- unsigned int short_packet_received : 1;
- unsigned int bad_lun_okay : 1;
-
- unsigned long atomic_bitflags;
-#define REGISTERED 0
-#define IGNORE_BULK_OUT 1
-#define SUSPENDED 2
-
- struct usb_ep *bulk_in;
- struct usb_ep *bulk_out;
- struct usb_ep *intr_in;
-
- struct fsg_buffhd *next_buffhd_to_fill;
- struct fsg_buffhd *next_buffhd_to_drain;
-
- int thread_wakeup_needed;
- struct completion thread_notifier;
- struct task_struct *thread_task;
-
- int cmnd_size;
- u8 cmnd[MAX_COMMAND_SIZE];
- enum data_direction data_dir;
- u32 data_size;
- u32 data_size_from_cmnd;
- u32 tag;
- unsigned int lun;
- u32 residue;
- u32 usb_amount_left;
-
- /* The CB protocol offers no way for a host to know when a command
- * has completed. As a result the next command may arrive early,
- * and we will still have to handle it. For that reason we need
- * a buffer to store new commands when using CB (or CBI, which
- * does not oblige a host to wait for command completion either). */
- int cbbuf_cmnd_size;
- u8 cbbuf_cmnd[MAX_COMMAND_SIZE];
-
- unsigned int nluns;
- struct fsg_lun *luns;
- struct fsg_lun *curlun;
- /* Must be the last entry */
- struct fsg_buffhd buffhds[];
-};
-
-typedef void (*fsg_routine_t)(struct fsg_dev *);
-
-static int exception_in_progress(struct fsg_dev *fsg)
-{
- return (fsg->state > FSG_STATE_IDLE);
-}
-
-/* Make bulk-out requests be divisible by the maxpacket size */
-static void set_bulk_out_req_length(struct fsg_dev *fsg,
- struct fsg_buffhd *bh, unsigned int length)
-{
- unsigned int rem;
-
- bh->bulk_out_intended_length = length;
- rem = length % fsg->bulk_out_maxpacket;
- if (rem > 0)
- length += fsg->bulk_out_maxpacket - rem;
- bh->outreq->length = length;
-}
-
-static struct fsg_dev *the_fsg;
-static struct usb_gadget_driver fsg_driver;
-
-
-/*-------------------------------------------------------------------------*/
-
-static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
-{
- const char *name;
-
- if (ep == fsg->bulk_in)
- name = "bulk-in";
- else if (ep == fsg->bulk_out)
- name = "bulk-out";
- else
- name = ep->name;
- DBG(fsg, "%s set halt\n", name);
- return usb_ep_set_halt(ep);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * DESCRIPTORS ... most are static, but strings and (full) configuration
- * descriptors are built on demand. Also the (static) config and interface
- * descriptors are adjusted during fsg_bind().
- */
-
-/* There is only one configuration. */
-#define CONFIG_VALUE 1
-
-static struct usb_device_descriptor
-device_desc = {
- .bLength = sizeof device_desc,
- .bDescriptorType = USB_DT_DEVICE,
-
- .bcdUSB = cpu_to_le16(0x0200),
- .bDeviceClass = USB_CLASS_PER_INTERFACE,
-
- /* The next three values can be overridden by module parameters */
- .idVendor = cpu_to_le16(FSG_VENDOR_ID),
- .idProduct = cpu_to_le16(FSG_PRODUCT_ID),
- .bcdDevice = cpu_to_le16(0xffff),
-
- .iManufacturer = FSG_STRING_MANUFACTURER,
- .iProduct = FSG_STRING_PRODUCT,
- .iSerialNumber = FSG_STRING_SERIAL,
- .bNumConfigurations = 1,
-};
-
-static struct usb_config_descriptor
-config_desc = {
- .bLength = sizeof config_desc,
- .bDescriptorType = USB_DT_CONFIG,
-
- /* wTotalLength computed by usb_gadget_config_buf() */
- .bNumInterfaces = 1,
- .bConfigurationValue = CONFIG_VALUE,
- .iConfiguration = FSG_STRING_CONFIG,
- .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2,
-};
-
-
-static struct usb_qualifier_descriptor
-dev_qualifier = {
- .bLength = sizeof dev_qualifier,
- .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
-
- .bcdUSB = cpu_to_le16(0x0200),
- .bDeviceClass = USB_CLASS_PER_INTERFACE,
-
- .bNumConfigurations = 1,
-};
-
-static int populate_bos(struct fsg_dev *fsg, u8 *buf)
-{
- memcpy(buf, &fsg_bos_desc, USB_DT_BOS_SIZE);
- buf += USB_DT_BOS_SIZE;
-
- memcpy(buf, &fsg_ext_cap_desc, USB_DT_USB_EXT_CAP_SIZE);
- buf += USB_DT_USB_EXT_CAP_SIZE;
-
- memcpy(buf, &fsg_ss_cap_desc, USB_DT_USB_SS_CAP_SIZE);
-
- return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE
- + USB_DT_USB_EXT_CAP_SIZE;
-}
-
-/*
- * Config descriptors must agree with the code that sets configurations
- * and with code managing interfaces and their altsettings. They must
- * also handle different speeds and other-speed requests.
- */
-static int populate_config_buf(struct usb_gadget *gadget,
- u8 *buf, u8 type, unsigned index)
-{
- enum usb_device_speed speed = gadget->speed;
- int len;
- const struct usb_descriptor_header **function;
-
- if (index > 0)
- return -EINVAL;
-
- if (gadget_is_dualspeed(gadget) && type == USB_DT_OTHER_SPEED_CONFIG)
- speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed;
- function = gadget_is_dualspeed(gadget) && speed == USB_SPEED_HIGH
- ? (const struct usb_descriptor_header **)fsg_hs_function
- : (const struct usb_descriptor_header **)fsg_fs_function;
-
- /* for now, don't advertise srp-only devices */
- if (!gadget_is_otg(gadget))
- function++;
-
- len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function);
- ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
- return len;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* These routines may be called in process context or in_irq */
-
-/* Caller must hold fsg->lock */
-static void wakeup_thread(struct fsg_dev *fsg)
-{
- /* Tell the main thread that something has happened */
- fsg->thread_wakeup_needed = 1;
- if (fsg->thread_task)
- wake_up_process(fsg->thread_task);
-}
-
-
-static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state)
-{
- unsigned long flags;
-
- /* Do nothing if a higher-priority exception is already in progress.
- * If a lower-or-equal priority exception is in progress, preempt it
- * and notify the main thread by sending it a signal. */
- spin_lock_irqsave(&fsg->lock, flags);
- if (fsg->state <= new_state) {
- fsg->exception_req_tag = fsg->ep0_req_tag;
- fsg->state = new_state;
- if (fsg->thread_task)
- send_sig_info(SIGUSR1, SEND_SIG_FORCED,
- fsg->thread_task);
- }
- spin_unlock_irqrestore(&fsg->lock, flags);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* The disconnect callback and ep0 routines. These always run in_irq,
- * except that ep0_queue() is called in the main thread to acknowledge
- * completion of various requests: set config, set interface, and
- * Bulk-only device reset. */
-
-static void fsg_disconnect(struct usb_gadget *gadget)
-{
- struct fsg_dev *fsg = get_gadget_data(gadget);
-
- DBG(fsg, "disconnect or port reset\n");
- raise_exception(fsg, FSG_STATE_DISCONNECT);
-}
-
-
-static int ep0_queue(struct fsg_dev *fsg)
-{
- int rc;
-
- rc = usb_ep_queue(fsg->ep0, fsg->ep0req, GFP_ATOMIC);
- if (rc != 0 && rc != -ESHUTDOWN) {
-
- /* We can't do much more than wait for a reset */
- WARNING(fsg, "error in submission: %s --> %d\n",
- fsg->ep0->name, rc);
- }
- return rc;
-}
-
-static void ep0_complete(struct usb_ep *ep, struct usb_request *req)
-{
- struct fsg_dev *fsg = ep->driver_data;
-
- if (req->actual > 0)
- dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual);
- if (req->status || req->actual != req->length)
- DBG(fsg, "%s --> %d, %u/%u\n", __func__,
- req->status, req->actual, req->length);
- if (req->status == -ECONNRESET) // Request was cancelled
- usb_ep_fifo_flush(ep);
-
- if (req->status == 0 && req->context)
- ((fsg_routine_t) (req->context))(fsg);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Bulk and interrupt endpoint completion handlers.
- * These always run in_irq. */
-
-static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
-{
- struct fsg_dev *fsg = ep->driver_data;
- struct fsg_buffhd *bh = req->context;
-
- if (req->status || req->actual != req->length)
- DBG(fsg, "%s --> %d, %u/%u\n", __func__,
- req->status, req->actual, req->length);
- if (req->status == -ECONNRESET) // Request was cancelled
- usb_ep_fifo_flush(ep);
-
- /* Hold the lock while we update the request and buffer states */
- smp_wmb();
- spin_lock(&fsg->lock);
- bh->inreq_busy = 0;
- bh->state = BUF_STATE_EMPTY;
- wakeup_thread(fsg);
- spin_unlock(&fsg->lock);
-}
-
-static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
-{
- struct fsg_dev *fsg = ep->driver_data;
- struct fsg_buffhd *bh = req->context;
-
- dump_msg(fsg, "bulk-out", req->buf, req->actual);
- if (req->status || req->actual != bh->bulk_out_intended_length)
- DBG(fsg, "%s --> %d, %u/%u\n", __func__,
- req->status, req->actual,
- bh->bulk_out_intended_length);
- if (req->status == -ECONNRESET) // Request was cancelled
- usb_ep_fifo_flush(ep);
-
- /* Hold the lock while we update the request and buffer states */
- smp_wmb();
- spin_lock(&fsg->lock);
- bh->outreq_busy = 0;
- bh->state = BUF_STATE_FULL;
- wakeup_thread(fsg);
- spin_unlock(&fsg->lock);
-}
-
-
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
-{
- struct fsg_dev *fsg = ep->driver_data;
- struct fsg_buffhd *bh = req->context;
-
- if (req->status || req->actual != req->length)
- DBG(fsg, "%s --> %d, %u/%u\n", __func__,
- req->status, req->actual, req->length);
- if (req->status == -ECONNRESET) // Request was cancelled
- usb_ep_fifo_flush(ep);
-
- /* Hold the lock while we update the request and buffer states */
- smp_wmb();
- spin_lock(&fsg->lock);
- fsg->intreq_busy = 0;
- bh->state = BUF_STATE_EMPTY;
- wakeup_thread(fsg);
- spin_unlock(&fsg->lock);
-}
-
-#else
-static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
-{}
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Ep0 class-specific handlers. These always run in_irq. */
-
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
- struct usb_request *req = fsg->ep0req;
- static u8 cbi_reset_cmnd[6] = {
- SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};
-
- /* Error in command transfer? */
- if (req->status || req->length != req->actual ||
- req->actual < 6 || req->actual > MAX_COMMAND_SIZE) {
-
- /* Not all controllers allow a protocol stall after
- * receiving control-out data, but we'll try anyway. */
- fsg_set_halt(fsg, fsg->ep0);
- return; // Wait for reset
- }
-
- /* Is it the special reset command? */
- if (req->actual >= sizeof cbi_reset_cmnd &&
- memcmp(req->buf, cbi_reset_cmnd,
- sizeof cbi_reset_cmnd) == 0) {
-
- /* Raise an exception to stop the current operation
- * and reinitialize our state. */
- DBG(fsg, "cbi reset request\n");
- raise_exception(fsg, FSG_STATE_RESET);
- return;
- }
-
- VDBG(fsg, "CB[I] accept device-specific command\n");
- spin_lock(&fsg->lock);
-
- /* Save the command for later */
- if (fsg->cbbuf_cmnd_size)
- WARNING(fsg, "CB[I] overwriting previous command\n");
- fsg->cbbuf_cmnd_size = req->actual;
- memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);
-
- wakeup_thread(fsg);
- spin_unlock(&fsg->lock);
-}
-
-#else
-static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{}
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
-
-static int class_setup_req(struct fsg_dev *fsg,
- const struct usb_ctrlrequest *ctrl)
-{
- struct usb_request *req = fsg->ep0req;
- int value = -EOPNOTSUPP;
- u16 w_index = le16_to_cpu(ctrl->wIndex);
- u16 w_value = le16_to_cpu(ctrl->wValue);
- u16 w_length = le16_to_cpu(ctrl->wLength);
-
- if (!fsg->config)
- return value;
-
- /* Handle Bulk-only class-specific requests */
- if (transport_is_bbb()) {
- switch (ctrl->bRequest) {
-
- case US_BULK_RESET_REQUEST:
- if (ctrl->bRequestType != (USB_DIR_OUT |
- USB_TYPE_CLASS | USB_RECIP_INTERFACE))
- break;
- if (w_index != 0 || w_value != 0 || w_length != 0) {
- value = -EDOM;
- break;
- }
-
- /* Raise an exception to stop the current operation
- * and reinitialize our state. */
- DBG(fsg, "bulk reset request\n");
- raise_exception(fsg, FSG_STATE_RESET);
- value = DELAYED_STATUS;
- break;
-
- case US_BULK_GET_MAX_LUN:
- if (ctrl->bRequestType != (USB_DIR_IN |
- USB_TYPE_CLASS | USB_RECIP_INTERFACE))
- break;
- if (w_index != 0 || w_value != 0 || w_length != 1) {
- value = -EDOM;
- break;
- }
- VDBG(fsg, "get max LUN\n");
- *(u8 *) req->buf = fsg->nluns - 1;
- value = 1;
- break;
- }
- }
-
- /* Handle CBI class-specific requests */
- else {
- switch (ctrl->bRequest) {
-
- case USB_CBI_ADSC_REQUEST:
- if (ctrl->bRequestType != (USB_DIR_OUT |
- USB_TYPE_CLASS | USB_RECIP_INTERFACE))
- break;
- if (w_index != 0 || w_value != 0) {
- value = -EDOM;
- break;
- }
- if (w_length > MAX_COMMAND_SIZE) {
- value = -EOVERFLOW;
- break;
- }
- value = w_length;
- fsg->ep0req->context = received_cbi_adsc;
- break;
- }
- }
-
- if (value == -EOPNOTSUPP)
- VDBG(fsg,
- "unknown class-specific control req "
- "%02x.%02x v%04x i%04x l%u\n",
- ctrl->bRequestType, ctrl->bRequest,
- le16_to_cpu(ctrl->wValue), w_index, w_length);
- return value;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Ep0 standard request handlers. These always run in_irq. */
-
-static int standard_setup_req(struct fsg_dev *fsg,
- const struct usb_ctrlrequest *ctrl)
-{
- struct usb_request *req = fsg->ep0req;
- int value = -EOPNOTSUPP;
- u16 w_index = le16_to_cpu(ctrl->wIndex);
- u16 w_value = le16_to_cpu(ctrl->wValue);
-
- /* Usually this just stores reply data in the pre-allocated ep0 buffer,
- * but config change events will also reconfigure hardware. */
- switch (ctrl->bRequest) {
-
- case USB_REQ_GET_DESCRIPTOR:
- if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
- USB_RECIP_DEVICE))
- break;
- switch (w_value >> 8) {
-
- case USB_DT_DEVICE:
- VDBG(fsg, "get device descriptor\n");
- device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket;
- value = sizeof device_desc;
- memcpy(req->buf, &device_desc, value);
- break;
- case USB_DT_DEVICE_QUALIFIER:
- VDBG(fsg, "get device qualifier\n");
- if (!gadget_is_dualspeed(fsg->gadget) ||
- fsg->gadget->speed == USB_SPEED_SUPER)
- break;
- /*
- * Assume ep0 uses the same maxpacket value for both
- * speeds
- */
- dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;
- value = sizeof dev_qualifier;
- memcpy(req->buf, &dev_qualifier, value);
- break;
-
- case USB_DT_OTHER_SPEED_CONFIG:
- VDBG(fsg, "get other-speed config descriptor\n");
- if (!gadget_is_dualspeed(fsg->gadget) ||
- fsg->gadget->speed == USB_SPEED_SUPER)
- break;
- goto get_config;
- case USB_DT_CONFIG:
- VDBG(fsg, "get configuration descriptor\n");
-get_config:
- value = populate_config_buf(fsg->gadget,
- req->buf,
- w_value >> 8,
- w_value & 0xff);
- break;
-
- case USB_DT_STRING:
- VDBG(fsg, "get string descriptor\n");
-
- /* wIndex == language code */
- value = usb_gadget_get_string(&fsg_stringtab,
- w_value & 0xff, req->buf);
- break;
-
- case USB_DT_BOS:
- VDBG(fsg, "get bos descriptor\n");
-
- if (gadget_is_superspeed(fsg->gadget))
- value = populate_bos(fsg, req->buf);
- break;
- }
-
- break;
-
- /* One config, two speeds */
- case USB_REQ_SET_CONFIGURATION:
- if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD |
- USB_RECIP_DEVICE))
- break;
- VDBG(fsg, "set configuration\n");
- if (w_value == CONFIG_VALUE || w_value == 0) {
- fsg->new_config = w_value;
-
- /* Raise an exception to wipe out previous transaction
- * state (queued bufs, etc) and set the new config. */
- raise_exception(fsg, FSG_STATE_CONFIG_CHANGE);
- value = DELAYED_STATUS;
- }
- break;
- case USB_REQ_GET_CONFIGURATION:
- if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
- USB_RECIP_DEVICE))
- break;
- VDBG(fsg, "get configuration\n");
- *(u8 *) req->buf = fsg->config;
- value = 1;
- break;
-
- case USB_REQ_SET_INTERFACE:
- if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD |
- USB_RECIP_INTERFACE))
- break;
- if (fsg->config && w_index == 0) {
-
- /* Raise an exception to wipe out previous transaction
- * state (queued bufs, etc) and install the new
- * interface altsetting. */
- raise_exception(fsg, FSG_STATE_INTERFACE_CHANGE);
- value = DELAYED_STATUS;
- }
- break;
- case USB_REQ_GET_INTERFACE:
- if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
- USB_RECIP_INTERFACE))
- break;
- if (!fsg->config)
- break;
- if (w_index != 0) {
- value = -EDOM;
- break;
- }
- VDBG(fsg, "get interface\n");
- *(u8 *) req->buf = 0;
- value = 1;
- break;
-
- default:
- VDBG(fsg,
- "unknown control req %02x.%02x v%04x i%04x l%u\n",
- ctrl->bRequestType, ctrl->bRequest,
- w_value, w_index, le16_to_cpu(ctrl->wLength));
- }
-
- return value;
-}
-
-
-static int fsg_setup(struct usb_gadget *gadget,
- const struct usb_ctrlrequest *ctrl)
<