linux/drivers/usb/gadget/function/f_mass_storage.c

// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/*
 * f_mass_storage.c -- Mass Storage USB Composite Function
 *
 * Copyright (C) 2003-2008 Alan Stern
 * Copyright (C) 2009 Samsung Electronics
 *                    Author: Michal Nazarewicz <[email protected]>
 * All rights reserved.
 */

/*
 * The Mass Storage Function 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 composite
 * function for a USB device, it also illustrates a technique of
 * double-buffering for increased throughput.
 *
 * For more information about MSF and in particular its module
 * parameters and sysfs interface read the
 * <Documentation/usb/mass-storage.rst> file.
 */

/*
 * MSF is configured by specifying a fsg_config structure.  It has the
 * following fields:
 *
 *	nluns		Number of LUNs function have (anywhere from 1
 *				to FSG_MAX_LUNS).
 *	luns		An array of LUN configuration values.  This
 *				should be filled for each LUN that
 *				function will include (ie. for "nluns"
 *				LUNs).  Each element of the array has
 *				the following fields:
 *	->filename	The path to the backing file for the LUN.
 *				Required if LUN is not marked as
 *				removable.
 *	->ro		Flag specifying access to the LUN shall be
 *				read-only.  This is implied if CD-ROM
 *				emulation is enabled as well as when
 *				it was impossible to open "filename"
 *				in R/W mode.
 *	->removable	Flag specifying that LUN shall be indicated as
 *				being removable.
 *	->cdrom		Flag specifying that LUN shall be reported as
 *				being a CD-ROM.
 *	->nofua		Flag specifying that FUA flag in SCSI WRITE(10,12)
 *				commands for this LUN shall be ignored.
 *
 *	vendor_name
 *	product_name
 *	release		Information used as a reply to INQUIRY
 *				request.  To use default set to NULL,
 *				NULL, 0xffff respectively.  The first
 *				field should be 8 and the second 16
 *				characters or less.
 *
 *	can_stall	Set to permit function to halt bulk endpoints.
 *				Disabled on some USB devices known not
 *				to work correctly.  You should set it
 *				to true.
 *
 * If "removable" is not set for a LUN then a backing file must be
 * specified.  If it is set, then NULL filename means the LUN's medium
 * is not loaded (an empty string as "filename" in the fsg_config
 * structure causes error).  The CD-ROM emulation includes a single
 * data track and no audio tracks; hence there need be only one
 * backing file per LUN.
 *
 * This function is heavily based on "File-backed Storage Gadget" by
 * Alan Stern which in turn 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 MSF 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.  As of this moment, MSF
 * provides no way to deregister the gadget when thread dies -- maybe
 * a callback functions is needed.
 *
 * 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/kstrtox.h>
#include <linux/kthread.h>
#include <linux/sched/signal.h>
#include <linux/limits.h>
#include <linux/pagemap.h>
#include <linux/rwsem.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/freezer.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/unaligned.h>

#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/composite.h>

#include <linux/nospec.h>

#include "configfs.h"


/*------------------------------------------------------------------------*/

#define FSG_DRIVER_DESC
#define FSG_DRIVER_VERSION

static const char fsg_string_interface[] =;

#include "storage_common.h"
#include "f_mass_storage.h"

/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
static struct usb_string		fsg_strings[] =;

static struct usb_gadget_strings	fsg_stringtab =;

static struct usb_gadget_strings *fsg_strings_array[] =;

/*-------------------------------------------------------------------------*/

struct fsg_dev;
struct fsg_common;

/* Data shared by all the FSG instances. */
struct fsg_common {};

struct fsg_dev {};

static inline int __fsg_is_set(struct fsg_common *common,
			       const char *func, unsigned line)
{}

#define fsg_is_set(common)

static inline struct fsg_dev *fsg_from_func(struct usb_function *f)
{}

static int exception_in_progress(struct fsg_common *common)
{}

/* Make bulk-out requests be divisible by the maxpacket size */
static void set_bulk_out_req_length(struct fsg_common *common,
				    struct fsg_buffhd *bh, unsigned int length)
{}


/*-------------------------------------------------------------------------*/

static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
{}


/*-------------------------------------------------------------------------*/

/* These routines may be called in process context or in_irq */

static void __raise_exception(struct fsg_common *common, enum fsg_state new_state,
			      void *arg)
{}

static void raise_exception(struct fsg_common *common, enum fsg_state new_state)
{}

/*-------------------------------------------------------------------------*/

static int ep0_queue(struct fsg_common *common)
{}


/*-------------------------------------------------------------------------*/

/* Completion handlers. These always run in_irq. */

static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
{}

static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
{}

static int _fsg_common_get_max_lun(struct fsg_common *common)
{}

static int fsg_setup(struct usb_function *f,
		     const struct usb_ctrlrequest *ctrl)
{}


/*-------------------------------------------------------------------------*/

/* All the following routines run in process context */

/* Use this for bulk or interrupt transfers, not ep0 */
static int start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
			   struct usb_request *req)
{}

static bool start_in_transfer(struct fsg_common *common, struct fsg_buffhd *bh)
{}

static bool start_out_transfer(struct fsg_common *common, struct fsg_buffhd *bh)
{}

static int sleep_thread(struct fsg_common *common, bool can_freeze,
		struct fsg_buffhd *bh)
{}


/*-------------------------------------------------------------------------*/

static int do_read(struct fsg_common *common)
{}


/*-------------------------------------------------------------------------*/

static int do_write(struct fsg_common *common)
{}


/*-------------------------------------------------------------------------*/

static int do_synchronize_cache(struct fsg_common *common)
{}


/*-------------------------------------------------------------------------*/

static void invalidate_sub(struct fsg_lun *curlun)
{}

static int do_verify(struct fsg_common *common)
{}


/*-------------------------------------------------------------------------*/

static int do_inquiry(struct fsg_common *common, struct fsg_buffhd *bh)
{}

static int do_request_sense(struct fsg_common *common, struct fsg_buffhd *bh)
{}

static int do_read_capacity(struct fsg_common *common, struct fsg_buffhd *bh)
{}

static int do_read_capacity_16(struct fsg_common *common, struct fsg_buffhd *bh)
{}

static int do_read_header(struct fsg_common *common, struct fsg_buffhd *bh)
{}

static int do_read_toc(struct fsg_common *common, struct fsg_buffhd *bh)
{}

static int do_mode_sense(struct fsg_common *common, struct fsg_buffhd *bh)
{}

static int do_start_stop(struct fsg_common *common)
{}

static int do_prevent_allow(struct fsg_common *common)
{}

static int do_read_format_capacities(struct fsg_common *common,
			struct fsg_buffhd *bh)
{}

static int do_mode_select(struct fsg_common *common, struct fsg_buffhd *bh)
{}


/*-------------------------------------------------------------------------*/

static int halt_bulk_in_endpoint(struct fsg_dev *fsg)
{}

static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
{}

static int throw_away_data(struct fsg_common *common)
{}

static int finish_reply(struct fsg_common *common)
{}

static void send_status(struct fsg_common *common)
{}


/*-------------------------------------------------------------------------*/

/*
 * Check whether the command is properly formed and whether its data size
 * and direction agree with the values we already have.
 */
static int check_command(struct fsg_common *common, int cmnd_size,
			 enum data_direction data_dir, unsigned int mask,
			 int needs_medium, const char *name)
{}

/* wrapper of check_command for data size in blocks handling */
static int check_command_size_in_blocks(struct fsg_common *common,
		int cmnd_size, enum data_direction data_dir,
		unsigned int mask, int needs_medium, const char *name)
{}

static int do_scsi_command(struct fsg_common *common)
{}


/*-------------------------------------------------------------------------*/

static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
{}

static int get_next_command(struct fsg_common *common)
{}


/*-------------------------------------------------------------------------*/

static int alloc_request(struct fsg_common *common, struct usb_ep *ep,
		struct usb_request **preq)
{}

/* Reset interface setting and re-init endpoint state (toggle etc). */
static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg)
{}


/****************************** ALT CONFIGS ******************************/

static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
{}

static void fsg_disable(struct usb_function *f)
{}


/*-------------------------------------------------------------------------*/

static void handle_exception(struct fsg_common *common)
{}


/*-------------------------------------------------------------------------*/

static int fsg_main_thread(void *common_)
{}


/*************************** DEVICE ATTRIBUTES ***************************/

static ssize_t ro_show(struct device *dev, struct device_attribute *attr, char *buf)
{}

static ssize_t nofua_show(struct device *dev, struct device_attribute *attr,
			  char *buf)
{}

static ssize_t file_show(struct device *dev, struct device_attribute *attr,
			 char *buf)
{}

static ssize_t ro_store(struct device *dev, struct device_attribute *attr,
			const char *buf, size_t count)
{}

static ssize_t nofua_store(struct device *dev, struct device_attribute *attr,
			   const char *buf, size_t count)
{}

static ssize_t file_store(struct device *dev, struct device_attribute *attr,
			  const char *buf, size_t count)
{}

static ssize_t forced_eject_store(struct device *dev,
				  struct device_attribute *attr,
				  const char *buf, size_t count)
{}

static DEVICE_ATTR_RW(nofua);
static DEVICE_ATTR_WO(forced_eject);

/*
 * Mode of the ro and file attribute files will be overridden in
 * fsg_lun_dev_is_visible() depending on if this is a cdrom, or if it is a
 * removable device.
 */
static DEVICE_ATTR_RW(ro);
static DEVICE_ATTR_RW(file);

/****************************** FSG COMMON ******************************/

static void fsg_lun_release(struct device *dev)
{}

static struct fsg_common *fsg_common_setup(struct fsg_common *common)
{}

void fsg_common_set_sysfs(struct fsg_common *common, bool sysfs)
{}
EXPORT_SYMBOL_GPL();

static void _fsg_common_free_buffers(struct fsg_buffhd *buffhds, unsigned n)
{}

int fsg_common_set_num_buffers(struct fsg_common *common, unsigned int n)
{}
EXPORT_SYMBOL_GPL();

void fsg_common_remove_lun(struct fsg_lun *lun)
{}
EXPORT_SYMBOL_GPL();

static void _fsg_common_remove_luns(struct fsg_common *common, int n)
{}

void fsg_common_remove_luns(struct fsg_common *common)
{}
EXPORT_SYMBOL_GPL();

void fsg_common_free_buffers(struct fsg_common *common)
{}
EXPORT_SYMBOL_GPL();

int fsg_common_set_cdev(struct fsg_common *common,
			 struct usb_composite_dev *cdev, bool can_stall)
{}
EXPORT_SYMBOL_GPL();

static struct attribute *fsg_lun_dev_attrs[] =;

static umode_t fsg_lun_dev_is_visible(struct kobject *kobj,
				      struct attribute *attr, int idx)
{}

static const struct attribute_group fsg_lun_dev_group =;

static const struct attribute_group *fsg_lun_dev_groups[] =;

int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
			  unsigned int id, const char *name,
			  const char **name_pfx)
{}
EXPORT_SYMBOL_GPL();

int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg)
{}
EXPORT_SYMBOL_GPL();

void fsg_common_set_inquiry_string(struct fsg_common *common, const char *vn,
				   const char *pn)
{}
EXPORT_SYMBOL_GPL();

static void fsg_common_release(struct fsg_common *common)
{}


/*-------------------------------------------------------------------------*/

static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
{}

/****************************** ALLOCATE FUNCTION *************************/

static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
{}

static inline struct fsg_lun_opts *to_fsg_lun_opts(struct config_item *item)
{}

static inline struct fsg_opts *to_fsg_opts(struct config_item *item)
{}

static void fsg_lun_attr_release(struct config_item *item)
{}

static struct configfs_item_operations fsg_lun_item_ops =;

static ssize_t fsg_lun_opts_file_show(struct config_item *item, char *page)
{}

static ssize_t fsg_lun_opts_file_store(struct config_item *item,
				       const char *page, size_t len)
{}

CONFIGFS_ATTR();

static ssize_t fsg_lun_opts_ro_show(struct config_item *item, char *page)
{}

static ssize_t fsg_lun_opts_ro_store(struct config_item *item,
				       const char *page, size_t len)
{}

CONFIGFS_ATTR();

static ssize_t fsg_lun_opts_removable_show(struct config_item *item,
					   char *page)
{}

static ssize_t fsg_lun_opts_removable_store(struct config_item *item,
				       const char *page, size_t len)
{}

CONFIGFS_ATTR();

static ssize_t fsg_lun_opts_cdrom_show(struct config_item *item, char *page)
{}

static ssize_t fsg_lun_opts_cdrom_store(struct config_item *item,
				       const char *page, size_t len)
{}

CONFIGFS_ATTR();

static ssize_t fsg_lun_opts_nofua_show(struct config_item *item, char *page)
{}

static ssize_t fsg_lun_opts_nofua_store(struct config_item *item,
				       const char *page, size_t len)
{}

CONFIGFS_ATTR();

static ssize_t fsg_lun_opts_inquiry_string_show(struct config_item *item,
						char *page)
{}

static ssize_t fsg_lun_opts_inquiry_string_store(struct config_item *item,
						 const char *page, size_t len)
{}

CONFIGFS_ATTR();

static ssize_t fsg_lun_opts_forced_eject_store(struct config_item *item,
					       const char *page, size_t len)
{}

CONFIGFS_ATTR_WO();

static struct configfs_attribute *fsg_lun_attrs[] =;

static const struct config_item_type fsg_lun_type =;

static struct config_group *fsg_lun_make(struct config_group *group,
					 const char *name)
{}

static void fsg_lun_drop(struct config_group *group, struct config_item *item)
{}

static void fsg_attr_release(struct config_item *item)
{}

static struct configfs_item_operations fsg_item_ops =;

static ssize_t fsg_opts_stall_show(struct config_item *item, char *page)
{}

static ssize_t fsg_opts_stall_store(struct config_item *item, const char *page,
				    size_t len)
{}

CONFIGFS_ATTR();

#ifdef CONFIG_USB_GADGET_DEBUG_FILES
static ssize_t fsg_opts_num_buffers_show(struct config_item *item, char *page)
{}

static ssize_t fsg_opts_num_buffers_store(struct config_item *item,
					  const char *page, size_t len)
{}

CONFIGFS_ATTR();
#endif

static struct configfs_attribute *fsg_attrs[] =;

static struct configfs_group_operations fsg_group_ops =;

static const struct config_item_type fsg_func_type =;

static void fsg_free_inst(struct usb_function_instance *fi)
{}

static struct usb_function_instance *fsg_alloc_inst(void)
{}

static void fsg_free(struct usb_function *f)
{}

static struct usb_function *fsg_alloc(struct usb_function_instance *fi)
{}

DECLARE_USB_FUNCTION_INIT(mass_storage, fsg_alloc_inst, fsg_alloc);
MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_AUTHOR();

/************************* Module parameters *************************/


void fsg_config_from_params(struct fsg_config *cfg,
		       const struct fsg_module_parameters *params,
		       unsigned int fsg_num_buffers)
{}
EXPORT_SYMBOL_GPL();