usb: gadget: create a utility module for mass_storage
authorAndrzej Pietrasiewicz <andrzej.p@samsung.com>
Thu, 26 Sep 2013 12:38:16 +0000 (14:38 +0200)
committerFelipe Balbi <balbi@ti.com>
Tue, 1 Oct 2013 14:50:57 +0000 (09:50 -0500)
Converting to configfs requires making the f_mass_storage.c a module.

But first we need to get rid of "#include "storage_common.c".

This patch makes storage_common.c a separately compiled file, which is
built as a utility module named u_ms.ko. After all mass storage users are
converted to the new function interface this module can be eliminated
by merging it with the mass storage function's module.

USB descriptors are exported so that they can be accessed from
f_mass_storage.

FSG_VENDOR_ID and FSG_PRODUCT_ID are moved to their only user.

Handling of CONFIG_USB_GADGET_DEBUG_FILES is moved to f_mass_storage.c.
The fsg_num_buffers static is moved to FSG_MODULE_PARAMETER users, so
instead of using a global variable the f_mass_storage introduces
fsg_num_buffers member in fsg_common (and fsg_config).

fsg_strings and fsg_stringtab are moved to f_mass_storage.c.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/gadget/Kconfig
drivers/usb/gadget/Makefile
drivers/usb/gadget/acm_ms.c
drivers/usb/gadget/f_mass_storage.c
drivers/usb/gadget/mass_storage.c
drivers/usb/gadget/multi.c
drivers/usb/gadget/storage_common.c
drivers/usb/gadget/storage_common.h [new file with mode: 0644]

index 48cddf3..98220dc 100644 (file)
@@ -525,6 +525,9 @@ config USB_F_SUBSET
 config USB_F_RNDIS
        tristate
 
+config USB_U_MS
+       tristate
+
 choice
        tristate "USB Gadget Drivers"
        default USB_ETH
@@ -878,6 +881,7 @@ config USB_MASS_STORAGE
        tristate "Mass Storage Gadget"
        depends on BLOCK
        select USB_LIBCOMPOSITE
+       select USB_U_MS
        help
          The Mass Storage Gadget acts as a USB Mass Storage disk drive.
          As its storage repository it can use a regular file or a block
@@ -1001,6 +1005,7 @@ config USB_G_ACM_MS
        select USB_LIBCOMPOSITE
        select USB_U_SERIAL
        select USB_F_ACM
+       select USB_U_MS
        help
          This driver provides two functions in one configuration:
          a mass storage, and a CDC ACM (serial port) link.
@@ -1017,6 +1022,7 @@ config USB_G_MULTI
        select USB_U_ETHER
        select USB_U_RNDIS
        select USB_F_ACM
+       select USB_U_MS
        help
          The Multifunction Composite Gadget provides Ethernet (RNDIS
          and/or CDC Ethernet), mass storage and ACM serial link
index 386db9d..d90a0b0 100644 (file)
@@ -60,6 +60,8 @@ usb_f_ecm_subset-y            := f_subset.o
 obj-$(CONFIG_USB_F_SUBSET)     += usb_f_ecm_subset.o
 usb_f_rndis-y                  := f_rndis.o
 obj-$(CONFIG_USB_F_RNDIS)      += usb_f_rndis.o
+u_ms-y                         := storage_common.o
+obj-$(CONFIG_USB_U_MS)         += u_ms.o
 
 #
 # USB gadget drivers
index 4b947bb..992ffb0 100644 (file)
@@ -104,6 +104,20 @@ static struct usb_gadget_strings *dev_strings[] = {
 /****************************** Configurations ******************************/
 
 static struct fsg_module_parameters fsg_mod_data = { .stall = 1 };
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+
+static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
+
+#else
+
+/*
+ * Number of buffers we will use.
+ * 2 is usually enough for good buffering pipeline
+ */
+#define fsg_num_buffers        CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
+
+#endif /* CONFIG_USB_DEBUG */
+
 FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
 
 static struct fsg_common fsg_common;
@@ -167,7 +181,8 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
        void                    *retp;
 
        /* set up mass storage function */
-       retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data);
+       retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data,
+                                     fsg_num_buffers);
        if (IS_ERR(retp)) {
                status = PTR_ERR(retp);
                return PTR_ERR(retp);
index a01d7d3..def3426 100644 (file)
 
 static const char fsg_string_interface[] = "Mass Storage";
 
-#include "storage_common.c"
+#include "storage_common.h"
 
+/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
+static struct usb_string               fsg_strings[] = {
+       {FSG_STRING_INTERFACE,          fsg_string_interface},
+       {}
+};
+
+static struct usb_gadget_strings       fsg_stringtab = {
+       .language       = 0x0409,               /* en-us */
+       .strings        = fsg_strings,
+};
 
 /*-------------------------------------------------------------------------*/
 
@@ -268,6 +278,7 @@ struct fsg_common {
        struct fsg_buffhd       *next_buffhd_to_fill;
        struct fsg_buffhd       *next_buffhd_to_drain;
        struct fsg_buffhd       *buffhds;
+       unsigned int            fsg_num_buffers;
 
        int                     cmnd_size;
        u8                      cmnd[MAX_COMMAND_SIZE];
@@ -332,6 +343,7 @@ struct fsg_config {
        const char *product_name;               /* 16 characters or less */
 
        char                    can_stall;
+       unsigned int            fsg_num_buffers;
 };
 
 struct fsg_dev {
@@ -2244,7 +2256,7 @@ reset:
        if (common->fsg) {
                fsg = common->fsg;
 
-               for (i = 0; i < fsg_num_buffers; ++i) {
+               for (i = 0; i < common->fsg_num_buffers; ++i) {
                        struct fsg_buffhd *bh = &common->buffhds[i];
 
                        if (bh->inreq) {
@@ -2303,7 +2315,7 @@ reset:
        clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
 
        /* Allocate the requests */
-       for (i = 0; i < fsg_num_buffers; ++i) {
+       for (i = 0; i < common->fsg_num_buffers; ++i) {
                struct fsg_buffhd       *bh = &common->buffhds[i];
 
                rc = alloc_request(common, fsg->bulk_in, &bh->inreq);
@@ -2372,7 +2384,7 @@ static void handle_exception(struct fsg_common *common)
 
        /* Cancel all the pending transfers */
        if (likely(common->fsg)) {
-               for (i = 0; i < fsg_num_buffers; ++i) {
+               for (i = 0; i < common->fsg_num_buffers; ++i) {
                        bh = &common->buffhds[i];
                        if (bh->inreq_busy)
                                usb_ep_dequeue(common->fsg->bulk_in, bh->inreq);
@@ -2384,7 +2396,7 @@ static void handle_exception(struct fsg_common *common)
                /* Wait until everything is idle */
                for (;;) {
                        int num_active = 0;
-                       for (i = 0; i < fsg_num_buffers; ++i) {
+                       for (i = 0; i < common->fsg_num_buffers; ++i) {
                                bh = &common->buffhds[i];
                                num_active += bh->inreq_busy + bh->outreq_busy;
                        }
@@ -2407,7 +2419,7 @@ static void handle_exception(struct fsg_common *common)
         */
        spin_lock_irq(&common->lock);
 
-       for (i = 0; i < fsg_num_buffers; ++i) {
+       for (i = 0; i < common->fsg_num_buffers; ++i) {
                bh = &common->buffhds[i];
                bh->state = BUF_STATE_EMPTY;
        }
@@ -2580,6 +2592,41 @@ static int fsg_main_thread(void *common_)
 
 /*************************** DEVICE ATTRIBUTES ***************************/
 
+static ssize_t ro_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       return fsg_show_ro(dev, attr, buf);
+}
+
+static ssize_t nofua_show(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       return fsg_show_nofua(dev, attr, buf);
+}
+
+static ssize_t file_show(struct device *dev, struct device_attribute *attr,
+                        char *buf)
+{
+       return fsg_show_file(dev, attr, buf);
+}
+
+static ssize_t ro_store(struct device *dev, struct device_attribute *attr,
+                       const char *buf, size_t count)
+{
+       return fsg_store_ro(dev, attr, buf, count);
+}
+
+static ssize_t nofua_store(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+       return fsg_store_nofua(dev, attr, buf, count);
+}
+
+static ssize_t file_store(struct device *dev, struct device_attribute *attr,
+                         const char *buf, size_t count)
+{
+       return fsg_store_file(dev, attr, buf, count);
+}
+
 static DEVICE_ATTR_RW(ro);
 static DEVICE_ATTR_RW(nofua);
 static DEVICE_ATTR_RW(file);
@@ -2607,6 +2654,16 @@ static inline void fsg_common_put(struct fsg_common *common)
        kref_put(&common->ref, fsg_common_release);
 }
 
+/* check if fsg_num_buffers is within a valid range */
+static inline int fsg_num_buffers_validate(unsigned int fsg_num_buffers)
+{
+       if (fsg_num_buffers >= 2 && fsg_num_buffers <= 4)
+               return 0;
+       pr_err("fsg_num_buffers %u is out of range (%d to %d)\n",
+              fsg_num_buffers, 2, 4);
+       return -EINVAL;
+}
+
 static struct fsg_common *fsg_common_init(struct fsg_common *common,
                                          struct usb_composite_dev *cdev,
                                          struct fsg_config *cfg)
@@ -2618,7 +2675,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
        int nluns, i, rc;
        char *pathbuf;
 
-       rc = fsg_num_buffers_validate();
+       rc = fsg_num_buffers_validate(cfg->fsg_num_buffers);
        if (rc != 0)
                return ERR_PTR(rc);
 
@@ -2640,7 +2697,8 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
                common->free_storage_on_release = 0;
        }
 
-       common->buffhds = kcalloc(fsg_num_buffers,
+       common->fsg_num_buffers = cfg->fsg_num_buffers;
+       common->buffhds = kcalloc(common->fsg_num_buffers,
                                  sizeof *(common->buffhds), GFP_KERNEL);
        if (!common->buffhds) {
                if (common->free_storage_on_release)
@@ -2727,7 +2785,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
 
        /* Data buffers cyclic list */
        bh = common->buffhds;
-       i = fsg_num_buffers;
+       i = common->fsg_num_buffers;
        goto buffhds_first_it;
        do {
                bh->next = bh + 1;
@@ -2847,7 +2905,7 @@ static void fsg_common_release(struct kref *ref)
 
        {
                struct fsg_buffhd *bh = common->buffhds;
-               unsigned i = fsg_num_buffers;
+               unsigned i = common->fsg_num_buffers;
                do {
                        kfree(bh->buf);
                } while (++bh, --i);
@@ -3009,7 +3067,7 @@ struct fsg_module_parameters {
                           S_IRUGO);                                    \
        MODULE_PARM_DESC(prefix ## name, desc)
 
-#define FSG_MODULE_PARAMETERS(prefix, params)                          \
+#define __FSG_MODULE_PARAMETERS(prefix, params)                                \
        _FSG_MODULE_PARAM_ARRAY(prefix, params, file, charp,            \
                                "names of backing files or devices");   \
        _FSG_MODULE_PARAM_ARRAY(prefix, params, ro, bool,               \
@@ -3025,9 +3083,24 @@ struct fsg_module_parameters {
        _FSG_MODULE_PARAM(prefix, params, stall, bool,                  \
                          "false to prevent bulk stalls")
 
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+
+#define FSG_MODULE_PARAMETERS(prefix, params)                          \
+       __FSG_MODULE_PARAMETERS(prefix, params);                        \
+       module_param_named(num_buffers, fsg_num_buffers, uint, S_IRUGO);\
+       MODULE_PARM_DESC(num_buffers, "Number of pipeline buffers")
+#else
+
+#define FSG_MODULE_PARAMETERS(prefix, params)                          \
+       __FSG_MODULE_PARAMETERS(prefix, params)
+
+#endif
+
+
 static void
 fsg_config_from_params(struct fsg_config *cfg,
-                      const struct fsg_module_parameters *params)
+                      const struct fsg_module_parameters *params,
+                      unsigned int fsg_num_buffers)
 {
        struct fsg_lun_config *lun;
        unsigned i;
@@ -3055,19 +3128,22 @@ fsg_config_from_params(struct fsg_config *cfg,
 
        /* Finalise */
        cfg->can_stall = params->stall;
+       cfg->fsg_num_buffers = fsg_num_buffers;
 }
 
 static inline struct fsg_common *
 fsg_common_from_params(struct fsg_common *common,
                       struct usb_composite_dev *cdev,
-                      const struct fsg_module_parameters *params)
+                      const struct fsg_module_parameters *params,
+                      unsigned int fsg_num_buffers)
        __attribute__((unused));
 static inline struct fsg_common *
 fsg_common_from_params(struct fsg_common *common,
                       struct usb_composite_dev *cdev,
-                      const struct fsg_module_parameters *params)
+                      const struct fsg_module_parameters *params,
+                      unsigned int fsg_num_buffers)
 {
        struct fsg_config cfg;
-       fsg_config_from_params(&cfg, params);
+       fsg_config_from_params(&cfg, params, fsg_num_buffers);
        return fsg_common_init(common, cdev, &cfg);
 }
index 080e577..4723d1b 100644 (file)
 #define DRIVER_DESC            "Mass Storage Gadget"
 #define DRIVER_VERSION         "2009/09/11"
 
+/*
+ * Thanks to NetChip Technologies for donating this product ID.
+ *
+ * DO NOT REUSE THESE IDs with any other driver!!  Ever!!
+ * Instead:  allocate your own, using normal USB-IF procedures.
+ */
+#define FSG_VENDOR_ID  0x0525  /* NetChip */
+#define FSG_PRODUCT_ID 0xa4a5  /* Linux-USB File-backed Storage Gadget */
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -102,6 +111,20 @@ static struct usb_gadget_strings *dev_strings[] = {
 static struct fsg_module_parameters mod_data = {
        .stall = 1
 };
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+
+static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
+
+#else
+
+/*
+ * Number of buffers we will use.
+ * 2 is usually enough for good buffering pipeline
+ */
+#define fsg_num_buffers        CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
+
+#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
+
 FSG_MODULE_PARAMETERS(/* no prefix */, mod_data);
 
 static unsigned long msg_registered;
@@ -129,7 +152,7 @@ static int __init msg_do_config(struct usb_configuration *c)
                c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
        }
 
-       fsg_config_from_params(&config, &mod_data);
+       fsg_config_from_params(&config, &mod_data, fsg_num_buffers);
        config.ops = &ops;
 
        retp = fsg_common_init(&common, c->cdev, &config);
index 2339325..6867d9d 100644 (file)
@@ -132,6 +132,20 @@ static struct usb_gadget_strings *dev_strings[] = {
 /****************************** Configurations ******************************/
 
 static struct fsg_module_parameters fsg_mod_data = { .stall = 1 };
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+
+static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
+
+#else
+
+/*
+ * Number of buffers we will use.
+ * 2 is usually enough for good buffering pipeline
+ */
+#define fsg_num_buffers        CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
+
+#endif /* CONFIG_USB_DEBUG */
+
 FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
 
 static struct fsg_common fsg_common;
@@ -294,7 +308,8 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
        /* set up mass storage function */
        {
                void *retp;
-               retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data);
+               retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data,
+                                             fsg_num_buffers);
                if (IS_ERR(retp)) {
                        status = PTR_ERR(retp);
                        goto fail1;
index 08a1a32..3e2500f 100644 (file)
  * The valid range of num_buffers is: num >= 2 && num <= 4.
  */
 
+#include <linux/module.h>
+#include <linux/blkdev.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/usb/composite.h>
 
-#include <linux/usb/storage.h>
-#include <scsi/scsi.h>
-#include <asm/unaligned.h>
-
-
-/*
- * Thanks to NetChip Technologies for donating this product ID.
- *
- * DO NOT REUSE THESE IDs with any other driver!!  Ever!!
- * Instead:  allocate your own, using normal USB-IF procedures.
- */
-#define FSG_VENDOR_ID  0x0525  /* NetChip */
-#define FSG_PRODUCT_ID 0xa4a5  /* Linux-USB File-backed Storage Gadget */
-
-
-/*-------------------------------------------------------------------------*/
-
-
-#ifndef DEBUG
-#undef VERBOSE_DEBUG
-#undef DUMP_MSGS
-#endif /* !DEBUG */
-
-#ifdef VERBOSE_DEBUG
-#define VLDBG  LDBG
-#else
-#define VLDBG(lun, fmt, args...) do { } while (0)
-#endif /* VERBOSE_DEBUG */
-
-#define LDBG(lun, fmt, args...)   dev_dbg (&(lun)->dev, fmt, ## args)
-#define LERROR(lun, fmt, args...) dev_err (&(lun)->dev, fmt, ## args)
-#define LWARN(lun, fmt, args...)  dev_warn(&(lun)->dev, fmt, ## args)
-#define LINFO(lun, fmt, args...)  dev_info(&(lun)->dev, fmt, ## args)
-
-
-#ifdef DUMP_MSGS
-
-#  define dump_msg(fsg, /* const char * */ label,                      \
-                  /* const u8 * */ buf, /* unsigned */ length) do {    \
-       if (length < 512) {                                             \
-               DBG(fsg, "%s, length %u:\n", label, length);            \
-               print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET,      \
-                              16, 1, buf, length, 0);                  \
-       }                                                               \
-} while (0)
-
-#  define dump_cdb(fsg) do { } while (0)
-
-#else
-
-#  define dump_msg(fsg, /* const char * */ label, \
-                  /* const u8 * */ buf, /* unsigned */ length) do { } while (0)
-
-#  ifdef VERBOSE_DEBUG
-
-#    define dump_cdb(fsg)                                              \
-       print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE,      \
-                      16, 1, (fsg)->cmnd, (fsg)->cmnd_size, 0)         \
-
-#  else
-
-#    define dump_cdb(fsg) do { } while (0)
-
-#  endif /* VERBOSE_DEBUG */
-
-#endif /* DUMP_MSGS */
-
-/*-------------------------------------------------------------------------*/
-
-/* Length of a SCSI Command Data Block */
-#define MAX_COMMAND_SIZE       16
-
-/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
-#define SS_NO_SENSE                            0
-#define SS_COMMUNICATION_FAILURE               0x040800
-#define SS_INVALID_COMMAND                     0x052000
-#define SS_INVALID_FIELD_IN_CDB                        0x052400
-#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE  0x052100
-#define SS_LOGICAL_UNIT_NOT_SUPPORTED          0x052500
-#define SS_MEDIUM_NOT_PRESENT                  0x023a00
-#define SS_MEDIUM_REMOVAL_PREVENTED            0x055302
-#define SS_NOT_READY_TO_READY_TRANSITION       0x062800
-#define SS_RESET_OCCURRED                      0x062900
-#define SS_SAVING_PARAMETERS_NOT_SUPPORTED     0x053900
-#define SS_UNRECOVERED_READ_ERROR              0x031100
-#define SS_WRITE_ERROR                         0x030c02
-#define SS_WRITE_PROTECTED                     0x072700
-
-#define SK(x)          ((u8) ((x) >> 16))      /* Sense Key byte, etc. */
-#define ASC(x)         ((u8) ((x) >> 8))
-#define ASCQ(x)                ((u8) (x))
-
-
-/*-------------------------------------------------------------------------*/
-
-
-struct fsg_lun {
-       struct file     *filp;
-       loff_t          file_length;
-       loff_t          num_sectors;
-
-       unsigned int    initially_ro:1;
-       unsigned int    ro:1;
-       unsigned int    removable:1;
-       unsigned int    cdrom:1;
-       unsigned int    prevent_medium_removal:1;
-       unsigned int    registered:1;
-       unsigned int    info_valid:1;
-       unsigned int    nofua:1;
-
-       u32             sense_data;
-       u32             sense_data_info;
-       u32             unit_attention_data;
-
-       unsigned int    blkbits;        /* Bits of logical block size of bound block device */
-       unsigned int    blksize;        /* logical block size of bound block device */
-       struct device   dev;
-};
-
-static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
-{
-       return curlun->filp != NULL;
-}
+#include "storage_common.h"
 
 static inline struct fsg_lun *fsg_lun_from_dev(struct device *dev)
 {
        return container_of(dev, struct fsg_lun, dev);
 }
 
-
-/* Big enough to hold our biggest descriptor */
-#define EP0_BUFSIZE    256
-#define DELAYED_STATUS (EP0_BUFSIZE + 999)     /* An impossibly large value */
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-
-static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
-module_param_named(num_buffers, fsg_num_buffers, uint, S_IRUGO);
-MODULE_PARM_DESC(num_buffers, "Number of pipeline buffers");
-
-#else
-
-/*
- * Number of buffers we will use.
- * 2 is usually enough for good buffering pipeline
- */
-#define fsg_num_buffers        CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
-
-#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
-
-/* check if fsg_num_buffers is within a valid range */
-static inline int fsg_num_buffers_validate(void)
-{
-       if (fsg_num_buffers >= 2 && fsg_num_buffers <= 4)
-               return 0;
-       pr_err("fsg_num_buffers %u is out of range (%d to %d)\n",
-              fsg_num_buffers, 2 ,4);
-       return -EINVAL;
-}
-
-/* Default size of buffer length. */
-#define FSG_BUFLEN     ((u32)16384)
-
-/* Maximal number of LUNs supported in mass storage function */
-#define FSG_MAX_LUNS   8
-
-enum fsg_buffer_state {
-       BUF_STATE_EMPTY = 0,
-       BUF_STATE_FULL,
-       BUF_STATE_BUSY
-};
-
-struct fsg_buffhd {
-       void                            *buf;
-       enum fsg_buffer_state           state;
-       struct fsg_buffhd               *next;
-
-       /*
-        * The NetChip 2280 is faster, and handles some protocol faults
-        * better, if we don't submit any short bulk-out read requests.
-        * So we will record the intended request length here.
-        */
-       unsigned int                    bulk_out_intended_length;
-
-       struct usb_request              *inreq;
-       int                             inreq_busy;
-       struct usb_request              *outreq;
-       int                             outreq_busy;
-};
-
-enum fsg_state {
-       /* This one isn't used anywhere */
-       FSG_STATE_COMMAND_PHASE = -10,
-       FSG_STATE_DATA_PHASE,
-       FSG_STATE_STATUS_PHASE,
-
-       FSG_STATE_IDLE = 0,
-       FSG_STATE_ABORT_BULK_OUT,
-       FSG_STATE_RESET,
-       FSG_STATE_INTERFACE_CHANGE,
-       FSG_STATE_CONFIG_CHANGE,
-       FSG_STATE_DISCONNECT,
-       FSG_STATE_EXIT,
-       FSG_STATE_TERMINATED
-};
-
-enum data_direction {
-       DATA_DIR_UNKNOWN = 0,
-       DATA_DIR_FROM_HOST,
-       DATA_DIR_TO_HOST,
-       DATA_DIR_NONE
-};
-
-
-/*-------------------------------------------------------------------------*/
-
-
-static inline u32 get_unaligned_be24(u8 *buf)
-{
-       return 0xffffff & (u32) get_unaligned_be32(buf - 1);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-
-enum {
-       FSG_STRING_INTERFACE
-};
-
-
 /* There is only one interface. */
 
-static struct usb_interface_descriptor
-fsg_intf_desc = {
+struct usb_interface_descriptor fsg_intf_desc = {
        .bLength =              sizeof fsg_intf_desc,
        .bDescriptorType =      USB_DT_INTERFACE,
 
@@ -268,14 +48,14 @@ fsg_intf_desc = {
        .bInterfaceProtocol =   USB_PR_BULK,    /* Adjusted during fsg_bind() */
        .iInterface =           FSG_STRING_INTERFACE,
 };
+EXPORT_SYMBOL(fsg_intf_desc);
 
 /*
  * Three full-speed endpoint descriptors: bulk-in, bulk-out, and
  * interrupt-in.
  */
 
-static struct usb_endpoint_descriptor
-fsg_fs_bulk_in_desc = {
+struct usb_endpoint_descriptor fsg_fs_bulk_in_desc = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
 
@@ -283,9 +63,9 @@ fsg_fs_bulk_in_desc = {
        .bmAttributes =         USB_ENDPOINT_XFER_BULK,
        /* wMaxPacketSize set by autoconfiguration */
 };
+EXPORT_SYMBOL(fsg_fs_bulk_in_desc);
 
-static struct usb_endpoint_descriptor
-fsg_fs_bulk_out_desc = {
+struct usb_endpoint_descriptor fsg_fs_bulk_out_desc = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
 
@@ -293,13 +73,15 @@ fsg_fs_bulk_out_desc = {
        .bmAttributes =         USB_ENDPOINT_XFER_BULK,
        /* wMaxPacketSize set by autoconfiguration */
 };
+EXPORT_SYMBOL(fsg_fs_bulk_out_desc);
 
-static struct usb_descriptor_header *fsg_fs_function[] = {
+struct usb_descriptor_header *fsg_fs_function[] = {
        (struct usb_descriptor_header *) &fsg_intf_desc,
        (struct usb_descriptor_header *) &fsg_fs_bulk_in_desc,
        (struct usb_descriptor_header *) &fsg_fs_bulk_out_desc,
        NULL,
 };
+EXPORT_SYMBOL(fsg_fs_function);
 
 
 /*
@@ -310,8 +92,7 @@ static struct usb_descriptor_header *fsg_fs_function[] = {
  * and a "device qualifier" ... plus more construction options
  * for the configuration descriptor.
  */
-static struct usb_endpoint_descriptor
-fsg_hs_bulk_in_desc = {
+struct usb_endpoint_descriptor fsg_hs_bulk_in_desc = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
 
@@ -319,9 +100,9 @@ fsg_hs_bulk_in_desc = {
        .bmAttributes =         USB_ENDPOINT_XFER_BULK,
        .wMaxPacketSize =       cpu_to_le16(512),
 };
+EXPORT_SYMBOL(fsg_hs_bulk_in_desc);
 
-static struct usb_endpoint_descriptor
-fsg_hs_bulk_out_desc = {
+struct usb_endpoint_descriptor fsg_hs_bulk_out_desc = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
 
@@ -330,17 +111,18 @@ fsg_hs_bulk_out_desc = {
        .wMaxPacketSize =       cpu_to_le16(512),
        .bInterval =            1,      /* NAK every 1 uframe */
 };
+EXPORT_SYMBOL(fsg_hs_bulk_out_desc);
 
 
-static struct usb_descriptor_header *fsg_hs_function[] = {
+struct usb_descriptor_header *fsg_hs_function[] = {
        (struct usb_descriptor_header *) &fsg_intf_desc,
        (struct usb_descriptor_header *) &fsg_hs_bulk_in_desc,
        (struct usb_descriptor_header *) &fsg_hs_bulk_out_desc,
        NULL,
 };
+EXPORT_SYMBOL(fsg_hs_function);
 
-static struct usb_endpoint_descriptor
-fsg_ss_bulk_in_desc = {
+struct usb_endpoint_descriptor fsg_ss_bulk_in_desc = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
 
@@ -348,16 +130,17 @@ fsg_ss_bulk_in_desc = {
        .bmAttributes =         USB_ENDPOINT_XFER_BULK,
        .wMaxPacketSize =       cpu_to_le16(1024),
 };
+EXPORT_SYMBOL(fsg_ss_bulk_in_desc);
 
-static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = {
+struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = {
        .bLength =              sizeof(fsg_ss_bulk_in_comp_desc),
        .bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
 
        /*.bMaxBurst =          DYNAMIC, */
 };
+EXPORT_SYMBOL(fsg_ss_bulk_in_comp_desc);
 
-static struct usb_endpoint_descriptor
-fsg_ss_bulk_out_desc = {
+struct usb_endpoint_descriptor fsg_ss_bulk_out_desc = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
 
@@ -365,15 +148,17 @@ fsg_ss_bulk_out_desc = {
        .bmAttributes =         USB_ENDPOINT_XFER_BULK,
        .wMaxPacketSize =       cpu_to_le16(1024),
 };
+EXPORT_SYMBOL(fsg_ss_bulk_out_desc);
 
-static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = {
+struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = {
        .bLength =              sizeof(fsg_ss_bulk_in_comp_desc),
        .bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
 
        /*.bMaxBurst =          DYNAMIC, */
 };
+EXPORT_SYMBOL(fsg_ss_bulk_out_comp_desc);
 
-static struct usb_descriptor_header *fsg_ss_function[] = {
+struct usb_descriptor_header *fsg_ss_function[] = {
        (struct usb_descriptor_header *) &fsg_intf_desc,
        (struct usb_descriptor_header *) &fsg_ss_bulk_in_desc,
        (struct usb_descriptor_header *) &fsg_ss_bulk_in_comp_desc,
@@ -381,17 +166,7 @@ static struct usb_descriptor_header *fsg_ss_function[] = {
        (struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc,
        NULL,
 };
-
-/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
-static struct usb_string               fsg_strings[] = {
-       {FSG_STRING_INTERFACE,          fsg_string_interface},
-       {}
-};
-
-static struct usb_gadget_strings       fsg_stringtab = {
-       .language       = 0x0409,               /* en-us */
-       .strings        = fsg_strings,
-};
+EXPORT_SYMBOL(fsg_ss_function);
 
 
  /*-------------------------------------------------------------------------*/
@@ -401,7 +176,7 @@ static struct usb_gadget_strings    fsg_stringtab = {
  * the caller must own fsg->filesem for writing.
  */
 
-static void fsg_lun_close(struct fsg_lun *curlun)
+void fsg_lun_close(struct fsg_lun *curlun)
 {
        if (curlun->filp) {
                LDBG(curlun, "close backing file\n");
@@ -409,9 +184,9 @@ static void fsg_lun_close(struct fsg_lun *curlun)
                curlun->filp = NULL;
        }
 }
+EXPORT_SYMBOL(fsg_lun_close);
 
-
-static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
+int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
 {
        int                             ro;
        struct file                     *filp = NULL;
@@ -508,6 +283,7 @@ out:
        fput(filp);
        return rc;
 }
+EXPORT_SYMBOL(fsg_lun_open);
 
 
 /*-------------------------------------------------------------------------*/
@@ -516,7 +292,7 @@ out:
  * Sync the file data, don't bother with the metadata.
  * This code was copied from fs/buffer.c:sys_fdatasync().
  */
-static int fsg_lun_fsync_sub(struct fsg_lun *curlun)
+int fsg_lun_fsync_sub(struct fsg_lun *curlun)
 {
        struct file     *filp = curlun->filp;
 
@@ -524,8 +300,9 @@ static int fsg_lun_fsync_sub(struct fsg_lun *curlun)
                return 0;
        return vfs_fsync(filp, 1);
 }
+EXPORT_SYMBOL(fsg_lun_fsync_sub);
 
-static void store_cdrom_address(u8 *dest, int msf, u32 addr)
+void store_cdrom_address(u8 *dest, int msf, u32 addr)
 {
        if (msf) {
                /* Convert to Minutes-Seconds-Frames */
@@ -542,13 +319,13 @@ static void store_cdrom_address(u8 *dest, int msf, u32 addr)
                put_unaligned_be32(addr, dest);
        }
 }
-
+EXPORT_SYMBOL(store_cdrom_address);
 
 /*-------------------------------------------------------------------------*/
 
 
-static ssize_t ro_show(struct device *dev, struct device_attribute *attr,
-                      char *buf)
+ssize_t fsg_show_ro(struct device *dev, struct device_attribute *attr,
+                   char *buf)
 {
        struct fsg_lun  *curlun = fsg_lun_from_dev(dev);
 
@@ -556,17 +333,19 @@ static ssize_t ro_show(struct device *dev, struct device_attribute *attr,
                                  ? curlun->ro
                                  : curlun->initially_ro);
 }
+EXPORT_SYMBOL(fsg_show_ro);
 
-static ssize_t nofua_show(struct device *dev, struct device_attribute *attr,
-                         char *buf)
+ssize_t fsg_show_nofua(struct device *dev, struct device_attribute *attr,
+                      char *buf)
 {
        struct fsg_lun  *curlun = fsg_lun_from_dev(dev);
 
        return sprintf(buf, "%u\n", curlun->nofua);
 }
+EXPORT_SYMBOL(fsg_show_nofua);
 
-static ssize_t file_show(struct device *dev, struct device_attribute *attr,
-                        char *buf)
+ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr,
+                     char *buf)
 {
        struct fsg_lun  *curlun = fsg_lun_from_dev(dev);
        struct rw_semaphore     *filesem = dev_get_drvdata(dev);
@@ -591,10 +370,11 @@ static ssize_t file_show(struct device *dev, struct device_attribute *attr,
        up_read(filesem);
        return rc;
 }
+EXPORT_SYMBOL(fsg_show_file);
 
 
-static ssize_t ro_store(struct device *dev, struct device_attribute *attr,
-                       const char *buf, size_t count)
+ssize_t fsg_store_ro(struct device *dev, struct device_attribute *attr,
+                    const char *buf, size_t count)
 {
        ssize_t         rc;
        struct fsg_lun  *curlun = fsg_lun_from_dev(dev);
@@ -622,9 +402,10 @@ static ssize_t ro_store(struct device *dev, struct device_attribute *attr,
        up_read(filesem);
        return rc;
 }
+EXPORT_SYMBOL(fsg_store_ro);
 
-static ssize_t nofua_store(struct device *dev, struct device_attribute *attr,
-                          const char *buf, size_t count)
+ssize_t fsg_store_nofua(struct device *dev, struct device_attribute *attr,
+                       const char *buf, size_t count)
 {
        struct fsg_lun  *curlun = fsg_lun_from_dev(dev);
        unsigned        nofua;
@@ -642,9 +423,10 @@ static ssize_t nofua_store(struct device *dev, struct device_attribute *attr,
 
        return count;
 }
+EXPORT_SYMBOL(fsg_store_nofua);
 
-static ssize_t file_store(struct device *dev, struct device_attribute *attr,
-                         const char *buf, size_t count)
+ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr,
+                      const char *buf, size_t count)
 {
        struct fsg_lun  *curlun = fsg_lun_from_dev(dev);
        struct rw_semaphore     *filesem = dev_get_drvdata(dev);
@@ -674,3 +456,6 @@ static ssize_t file_store(struct device *dev, struct device_attribute *attr,
        up_write(filesem);
        return (rc < 0 ? rc : count);
 }
+EXPORT_SYMBOL(fsg_store_file);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/storage_common.h b/drivers/usb/gadget/storage_common.h
new file mode 100644 (file)
index 0000000..1fcda2b
--- /dev/null
@@ -0,0 +1,210 @@
+#ifndef USB_STORAGE_COMMON_H
+#define USB_STORAGE_COMMON_H
+
+#include <linux/device.h>
+#include <linux/usb/storage.h>
+#include <scsi/scsi.h>
+#include <asm/unaligned.h>
+
+#ifndef DEBUG
+#undef VERBOSE_DEBUG
+#undef DUMP_MSGS
+#endif /* !DEBUG */
+
+#ifdef VERBOSE_DEBUG
+#define VLDBG  LDBG
+#else
+#define VLDBG(lun, fmt, args...) do { } while (0)
+#endif /* VERBOSE_DEBUG */
+
+#define LDBG(lun, fmt, args...)   dev_dbg(&(lun)->dev, fmt, ## args)
+#define LERROR(lun, fmt, args...) dev_err(&(lun)->dev, fmt, ## args)
+#define LWARN(lun, fmt, args...)  dev_warn(&(lun)->dev, fmt, ## args)
+#define LINFO(lun, fmt, args...)  dev_info(&(lun)->dev, fmt, ## args)
+
+#ifdef DUMP_MSGS
+
+#  define dump_msg(fsg, /* const char * */ label,                      \
+                  /* const u8 * */ buf, /* unsigned */ length)         \
+do {                                                                   \
+       if (length < 512) {                                             \
+               DBG(fsg, "%s, length %u:\n", label, length);            \
+               print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET,      \
+                              16, 1, buf, length, 0);                  \
+       }                                                               \
+} while (0)
+
+#  define dump_cdb(fsg) do { } while (0)
+
+#else
+
+#  define dump_msg(fsg, /* const char * */ label, \
+                  /* const u8 * */ buf, /* unsigned */ length) do { } while (0)
+
+#  ifdef VERBOSE_DEBUG
+
+#    define dump_cdb(fsg)                                              \
+       print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE,      \
+                      16, 1, (fsg)->cmnd, (fsg)->cmnd_size, 0)         \
+
+#  else
+
+#    define dump_cdb(fsg) do { } while (0)
+
+#  endif /* VERBOSE_DEBUG */
+
+#endif /* DUMP_MSGS */
+
+/* Length of a SCSI Command Data Block */
+#define MAX_COMMAND_SIZE       16
+
+/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
+#define SS_NO_SENSE                            0
+#define SS_COMMUNICATION_FAILURE               0x040800
+#define SS_INVALID_COMMAND                     0x052000
+#define SS_INVALID_FIELD_IN_CDB                        0x052400
+#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE  0x052100
+#define SS_LOGICAL_UNIT_NOT_SUPPORTED          0x052500
+#define SS_MEDIUM_NOT_PRESENT                  0x023a00
+#define SS_MEDIUM_REMOVAL_PREVENTED            0x055302
+#define SS_NOT_READY_TO_READY_TRANSITION       0x062800
+#define SS_RESET_OCCURRED                      0x062900
+#define SS_SAVING_PARAMETERS_NOT_SUPPORTED     0x053900
+#define SS_UNRECOVERED_READ_ERROR              0x031100
+#define SS_WRITE_ERROR                         0x030c02
+#define SS_WRITE_PROTECTED                     0x072700
+
+#define SK(x)          ((u8) ((x) >> 16))      /* Sense Key byte, etc. */
+#define ASC(x)         ((u8) ((x) >> 8))
+#define ASCQ(x)                ((u8) (x))
+
+struct fsg_lun {
+       struct file     *filp;
+       loff_t          file_length;
+       loff_t          num_sectors;
+
+       unsigned int    initially_ro:1;
+       unsigned int    ro:1;
+       unsigned int    removable:1;
+       unsigned int    cdrom:1;
+       unsigned int    prevent_medium_removal:1;
+       unsigned int    registered:1;
+       unsigned int    info_valid:1;
+       unsigned int    nofua:1;
+
+       u32             sense_data;
+       u32             sense_data_info;
+       u32             unit_attention_data;
+
+       unsigned int    blkbits; /* Bits of logical block size
+                                                      of bound block device */
+       unsigned int    blksize; /* logical block size of bound block device */
+       struct device   dev;
+};
+
+static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
+{
+       return curlun->filp != NULL;
+}
+
+/* Big enough to hold our biggest descriptor */
+#define EP0_BUFSIZE    256
+#define DELAYED_STATUS (EP0_BUFSIZE + 999)     /* An impossibly large value */
+
+/* Default size of buffer length. */
+#define FSG_BUFLEN     ((u32)16384)
+
+/* Maximal number of LUNs supported in mass storage function */
+#define FSG_MAX_LUNS   8
+
+enum fsg_buffer_state {
+       BUF_STATE_EMPTY = 0,
+       BUF_STATE_FULL,
+       BUF_STATE_BUSY
+};
+
+struct fsg_buffhd {
+       void                            *buf;
+       enum fsg_buffer_state           state;
+       struct fsg_buffhd               *next;
+
+       /*
+        * The NetChip 2280 is faster, and handles some protocol faults
+        * better, if we don't submit any short bulk-out read requests.
+        * So we will record the intended request length here.
+        */
+       unsigned int                    bulk_out_intended_length;
+
+       struct usb_request              *inreq;
+       int                             inreq_busy;
+       struct usb_request              *outreq;
+       int                             outreq_busy;
+};
+
+enum fsg_state {
+       /* This one isn't used anywhere */
+       FSG_STATE_COMMAND_PHASE = -10,
+       FSG_STATE_DATA_PHASE,
+       FSG_STATE_STATUS_PHASE,
+
+       FSG_STATE_IDLE = 0,
+       FSG_STATE_ABORT_BULK_OUT,
+       FSG_STATE_RESET,
+       FSG_STATE_INTERFACE_CHANGE,
+       FSG_STATE_CONFIG_CHANGE,
+       FSG_STATE_DISCONNECT,
+       FSG_STATE_EXIT,
+       FSG_STATE_TERMINATED
+};
+
+enum data_direction {
+       DATA_DIR_UNKNOWN = 0,
+       DATA_DIR_FROM_HOST,
+       DATA_DIR_TO_HOST,
+       DATA_DIR_NONE
+};
+
+static inline u32 get_unaligned_be24(u8 *buf)
+{
+       return 0xffffff & (u32) get_unaligned_be32(buf - 1);
+}
+
+enum {
+       FSG_STRING_INTERFACE
+};
+
+extern struct usb_interface_descriptor fsg_intf_desc;
+
+extern struct usb_endpoint_descriptor fsg_fs_bulk_in_desc;
+extern struct usb_endpoint_descriptor fsg_fs_bulk_out_desc;
+extern struct usb_descriptor_header *fsg_fs_function[];
+
+extern struct usb_endpoint_descriptor fsg_hs_bulk_in_desc;
+extern struct usb_endpoint_descriptor fsg_hs_bulk_out_desc;
+extern struct usb_descriptor_header *fsg_hs_function[];
+
+extern struct usb_endpoint_descriptor fsg_ss_bulk_in_desc;
+extern struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc;
+extern struct usb_endpoint_descriptor fsg_ss_bulk_out_desc;
+extern struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc;
+extern struct usb_descriptor_header *fsg_ss_function[];
+
+void fsg_lun_close(struct fsg_lun *curlun);
+int fsg_lun_open(struct fsg_lun *curlun, const char *filename);
+int fsg_lun_fsync_sub(struct fsg_lun *curlun);
+void store_cdrom_address(u8 *dest, int msf, u32 addr);
+ssize_t fsg_show_ro(struct device *dev, struct device_attribute *attr,
+                   char *buf);
+ssize_t fsg_show_nofua(struct device *dev, struct device_attribute *attr,
+                      char *buf);
+ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr,
+                     char *buf);
+ssize_t fsg_store_ro(struct device *dev, struct device_attribute *attr,
+                    const char *buf, size_t count);
+ssize_t fsg_store_nofua(struct device *dev,
+                       struct device_attribute *attr,
+                       const char *buf, size_t count);
+ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr,
+                      const char *buf, size_t count);
+
+#endif /* USB_STORAGE_COMMON_H */