Commit 6fdc5dd2 authored by Andrzej Pietrasiewicz's avatar Andrzej Pietrasiewicz Committed by Felipe Balbi

usb: gadget: create a utility module for mass_storage

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: default avatarAndrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 092a4bd0
...@@ -525,6 +525,9 @@ config USB_F_SUBSET ...@@ -525,6 +525,9 @@ config USB_F_SUBSET
config USB_F_RNDIS config USB_F_RNDIS
tristate tristate
config USB_U_MS
tristate
choice choice
tristate "USB Gadget Drivers" tristate "USB Gadget Drivers"
default USB_ETH default USB_ETH
...@@ -878,6 +881,7 @@ config USB_MASS_STORAGE ...@@ -878,6 +881,7 @@ config USB_MASS_STORAGE
tristate "Mass Storage Gadget" tristate "Mass Storage Gadget"
depends on BLOCK depends on BLOCK
select USB_LIBCOMPOSITE select USB_LIBCOMPOSITE
select USB_U_MS
help help
The Mass Storage Gadget acts as a USB Mass Storage disk drive. 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 As its storage repository it can use a regular file or a block
...@@ -1001,6 +1005,7 @@ config USB_G_ACM_MS ...@@ -1001,6 +1005,7 @@ config USB_G_ACM_MS
select USB_LIBCOMPOSITE select USB_LIBCOMPOSITE
select USB_U_SERIAL select USB_U_SERIAL
select USB_F_ACM select USB_F_ACM
select USB_U_MS
help help
This driver provides two functions in one configuration: This driver provides two functions in one configuration:
a mass storage, and a CDC ACM (serial port) link. a mass storage, and a CDC ACM (serial port) link.
...@@ -1017,6 +1022,7 @@ config USB_G_MULTI ...@@ -1017,6 +1022,7 @@ config USB_G_MULTI
select USB_U_ETHER select USB_U_ETHER
select USB_U_RNDIS select USB_U_RNDIS
select USB_F_ACM select USB_F_ACM
select USB_U_MS
help help
The Multifunction Composite Gadget provides Ethernet (RNDIS The Multifunction Composite Gadget provides Ethernet (RNDIS
and/or CDC Ethernet), mass storage and ACM serial link and/or CDC Ethernet), mass storage and ACM serial link
......
...@@ -60,6 +60,8 @@ usb_f_ecm_subset-y := f_subset.o ...@@ -60,6 +60,8 @@ usb_f_ecm_subset-y := f_subset.o
obj-$(CONFIG_USB_F_SUBSET) += usb_f_ecm_subset.o obj-$(CONFIG_USB_F_SUBSET) += usb_f_ecm_subset.o
usb_f_rndis-y := f_rndis.o usb_f_rndis-y := f_rndis.o
obj-$(CONFIG_USB_F_RNDIS) += usb_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 # USB gadget drivers
......
...@@ -104,6 +104,20 @@ static struct usb_gadget_strings *dev_strings[] = { ...@@ -104,6 +104,20 @@ static struct usb_gadget_strings *dev_strings[] = {
/****************************** Configurations ******************************/ /****************************** Configurations ******************************/
static struct fsg_module_parameters fsg_mod_data = { .stall = 1 }; 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); FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
static struct fsg_common fsg_common; static struct fsg_common fsg_common;
...@@ -167,7 +181,8 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev) ...@@ -167,7 +181,8 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
void *retp; void *retp;
/* set up mass storage function */ /* 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)) { if (IS_ERR(retp)) {
status = PTR_ERR(retp); status = PTR_ERR(retp);
return PTR_ERR(retp); return PTR_ERR(retp);
......
...@@ -228,8 +228,18 @@ ...@@ -228,8 +228,18 @@
static const char fsg_string_interface[] = "Mass Storage"; 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 { ...@@ -268,6 +278,7 @@ struct fsg_common {
struct fsg_buffhd *next_buffhd_to_fill; struct fsg_buffhd *next_buffhd_to_fill;
struct fsg_buffhd *next_buffhd_to_drain; struct fsg_buffhd *next_buffhd_to_drain;
struct fsg_buffhd *buffhds; struct fsg_buffhd *buffhds;
unsigned int fsg_num_buffers;
int cmnd_size; int cmnd_size;
u8 cmnd[MAX_COMMAND_SIZE]; u8 cmnd[MAX_COMMAND_SIZE];
...@@ -332,6 +343,7 @@ struct fsg_config { ...@@ -332,6 +343,7 @@ struct fsg_config {
const char *product_name; /* 16 characters or less */ const char *product_name; /* 16 characters or less */
char can_stall; char can_stall;
unsigned int fsg_num_buffers;
}; };
struct fsg_dev { struct fsg_dev {
...@@ -2244,7 +2256,7 @@ static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg) ...@@ -2244,7 +2256,7 @@ static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg)
if (common->fsg) { if (common->fsg) {
fsg = 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]; struct fsg_buffhd *bh = &common->buffhds[i];
if (bh->inreq) { if (bh->inreq) {
...@@ -2303,7 +2315,7 @@ static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg) ...@@ -2303,7 +2315,7 @@ static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg)
clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
/* Allocate the requests */ /* 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]; struct fsg_buffhd *bh = &common->buffhds[i];
rc = alloc_request(common, fsg->bulk_in, &bh->inreq); rc = alloc_request(common, fsg->bulk_in, &bh->inreq);
...@@ -2372,7 +2384,7 @@ static void handle_exception(struct fsg_common *common) ...@@ -2372,7 +2384,7 @@ static void handle_exception(struct fsg_common *common)
/* Cancel all the pending transfers */ /* Cancel all the pending transfers */
if (likely(common->fsg)) { 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]; bh = &common->buffhds[i];
if (bh->inreq_busy) if (bh->inreq_busy)
usb_ep_dequeue(common->fsg->bulk_in, bh->inreq); usb_ep_dequeue(common->fsg->bulk_in, bh->inreq);
...@@ -2384,7 +2396,7 @@ static void handle_exception(struct fsg_common *common) ...@@ -2384,7 +2396,7 @@ static void handle_exception(struct fsg_common *common)
/* Wait until everything is idle */ /* Wait until everything is idle */
for (;;) { for (;;) {
int num_active = 0; 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]; bh = &common->buffhds[i];
num_active += bh->inreq_busy + bh->outreq_busy; num_active += bh->inreq_busy + bh->outreq_busy;
} }
...@@ -2407,7 +2419,7 @@ static void handle_exception(struct fsg_common *common) ...@@ -2407,7 +2419,7 @@ static void handle_exception(struct fsg_common *common)
*/ */
spin_lock_irq(&common->lock); 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 = &common->buffhds[i];
bh->state = BUF_STATE_EMPTY; bh->state = BUF_STATE_EMPTY;
} }
...@@ -2580,6 +2592,41 @@ static int fsg_main_thread(void *common_) ...@@ -2580,6 +2592,41 @@ static int fsg_main_thread(void *common_)
/*************************** DEVICE ATTRIBUTES ***************************/ /*************************** 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(ro);
static DEVICE_ATTR_RW(nofua); static DEVICE_ATTR_RW(nofua);
static DEVICE_ATTR_RW(file); static DEVICE_ATTR_RW(file);
...@@ -2607,6 +2654,16 @@ static inline void fsg_common_put(struct fsg_common *common) ...@@ -2607,6 +2654,16 @@ static inline void fsg_common_put(struct fsg_common *common)
kref_put(&common->ref, fsg_common_release); 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, static struct fsg_common *fsg_common_init(struct fsg_common *common,
struct usb_composite_dev *cdev, struct usb_composite_dev *cdev,
struct fsg_config *cfg) struct fsg_config *cfg)
...@@ -2618,7 +2675,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, ...@@ -2618,7 +2675,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
int nluns, i, rc; int nluns, i, rc;
char *pathbuf; char *pathbuf;
rc = fsg_num_buffers_validate(); rc = fsg_num_buffers_validate(cfg->fsg_num_buffers);
if (rc != 0) if (rc != 0)
return ERR_PTR(rc); return ERR_PTR(rc);
...@@ -2640,7 +2697,8 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, ...@@ -2640,7 +2697,8 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
common->free_storage_on_release = 0; 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); sizeof *(common->buffhds), GFP_KERNEL);
if (!common->buffhds) { if (!common->buffhds) {
if (common->free_storage_on_release) if (common->free_storage_on_release)
...@@ -2727,7 +2785,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, ...@@ -2727,7 +2785,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
/* Data buffers cyclic list */ /* Data buffers cyclic list */
bh = common->buffhds; bh = common->buffhds;
i = fsg_num_buffers; i = common->fsg_num_buffers;
goto buffhds_first_it; goto buffhds_first_it;
do { do {
bh->next = bh + 1; bh->next = bh + 1;
...@@ -2847,7 +2905,7 @@ static void fsg_common_release(struct kref *ref) ...@@ -2847,7 +2905,7 @@ static void fsg_common_release(struct kref *ref)
{ {
struct fsg_buffhd *bh = common->buffhds; struct fsg_buffhd *bh = common->buffhds;
unsigned i = fsg_num_buffers; unsigned i = common->fsg_num_buffers;
do { do {
kfree(bh->buf); kfree(bh->buf);
} while (++bh, --i); } while (++bh, --i);
...@@ -3009,7 +3067,7 @@ struct fsg_module_parameters { ...@@ -3009,7 +3067,7 @@ struct fsg_module_parameters {
S_IRUGO); \ S_IRUGO); \
MODULE_PARM_DESC(prefix ## name, desc) 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, \ _FSG_MODULE_PARAM_ARRAY(prefix, params, file, charp, \
"names of backing files or devices"); \ "names of backing files or devices"); \
_FSG_MODULE_PARAM_ARRAY(prefix, params, ro, bool, \ _FSG_MODULE_PARAM_ARRAY(prefix, params, ro, bool, \
...@@ -3025,9 +3083,24 @@ struct fsg_module_parameters { ...@@ -3025,9 +3083,24 @@ struct fsg_module_parameters {
_FSG_MODULE_PARAM(prefix, params, stall, bool, \ _FSG_MODULE_PARAM(prefix, params, stall, bool, \
"false to prevent bulk stalls") "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 static void
fsg_config_from_params(struct fsg_config *cfg, 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; struct fsg_lun_config *lun;
unsigned i; unsigned i;
...@@ -3055,19 +3128,22 @@ fsg_config_from_params(struct fsg_config *cfg, ...@@ -3055,19 +3128,22 @@ fsg_config_from_params(struct fsg_config *cfg,
/* Finalise */ /* Finalise */
cfg->can_stall = params->stall; cfg->can_stall = params->stall;
cfg->fsg_num_buffers = fsg_num_buffers;
} }
static inline struct fsg_common * static inline struct fsg_common *
fsg_common_from_params(struct fsg_common *common, fsg_common_from_params(struct fsg_common *common,
struct usb_composite_dev *cdev, struct usb_composite_dev *cdev,
const struct fsg_module_parameters *params) const struct fsg_module_parameters *params,
unsigned int fsg_num_buffers)
__attribute__((unused)); __attribute__((unused));
static inline struct fsg_common * static inline struct fsg_common *
fsg_common_from_params(struct fsg_common *common, fsg_common_from_params(struct fsg_common *common,
struct usb_composite_dev *cdev, 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; 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); return fsg_common_init(common, cdev, &cfg);
} }
...@@ -37,6 +37,15 @@ ...@@ -37,6 +37,15 @@
#define DRIVER_DESC "Mass Storage Gadget" #define DRIVER_DESC "Mass Storage Gadget"
#define DRIVER_VERSION "2009/09/11" #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[] = { ...@@ -102,6 +111,20 @@ static struct usb_gadget_strings *dev_strings[] = {
static struct fsg_module_parameters mod_data = { static struct fsg_module_parameters mod_data = {
.stall = 1 .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); FSG_MODULE_PARAMETERS(/* no prefix */, mod_data);
static unsigned long msg_registered; static unsigned long msg_registered;
...@@ -129,7 +152,7 @@ static int __init msg_do_config(struct usb_configuration *c) ...@@ -129,7 +152,7 @@ static int __init msg_do_config(struct usb_configuration *c)
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; 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; config.ops = &ops;
retp = fsg_common_init(&common, c->cdev, &config); retp = fsg_common_init(&common, c->cdev, &config);
......
...@@ -132,6 +132,20 @@ static struct usb_gadget_strings *dev_strings[] = { ...@@ -132,6 +132,20 @@ static struct usb_gadget_strings *dev_strings[] = {
/****************************** Configurations ******************************/ /****************************** Configurations ******************************/
static struct fsg_module_parameters fsg_mod_data = { .stall = 1 }; 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); FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
static struct fsg_common fsg_common; static struct fsg_common fsg_common;
...@@ -294,7 +308,8 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) ...@@ -294,7 +308,8 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
/* set up mass storage function */ /* set up mass storage function */
{ {
void *retp; 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)) { if (IS_ERR(retp)) {
status = PTR_ERR(retp); status = PTR_ERR(retp);
goto fail1; goto fail1;
......
...@@ -23,242 +23,22 @@ ...@@ -23,242 +23,22 @@
* The valid range of num_buffers is: num >= 2 && num <= 4. * 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 "storage_common.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;
}
static inline struct fsg_lun *fsg_lun_from_dev(struct device *dev) static inline struct fsg_lun *fsg_lun_from_dev(struct device *dev)
{ {
return container_of(dev, struct fsg_lun, 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. */ /* There is only one interface. */
static struct usb_interface_descriptor struct usb_interface_descriptor fsg_intf_desc = {
fsg_intf_desc = {
.bLength = sizeof fsg_intf_desc, .bLength = sizeof fsg_intf_desc,
.bDescriptorType = USB_DT_INTERFACE, .bDescriptorType = USB_DT_INTERFACE,
...@@ -268,14 +48,14 @@ fsg_intf_desc = { ...@@ -268,14 +48,14 @@ fsg_intf_desc = {
.bInterfaceProtocol = USB_PR_BULK, /* Adjusted during fsg_bind() */ .bInterfaceProtocol = USB_PR_BULK, /* Adjusted during fsg_bind() */
.iInterface = FSG_STRING_INTERFACE, .iInterface = FSG_STRING_INTERFACE,
}; };
EXPORT_SYMBOL(fsg_intf_desc);
/* /*
* Three full-speed endpoint descriptors: bulk-in, bulk-out, and * Three full-speed endpoint descriptors: bulk-in, bulk-out, and
* interrupt-in. * interrupt-in.
*/ */
static struct usb_endpoint_descriptor struct usb_endpoint_descriptor fsg_fs_bulk_in_desc = {
fsg_fs_bulk_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
...@@ -283,9 +63,9 @@ fsg_fs_bulk_in_desc = { ...@@ -283,9 +63,9 @@ fsg_fs_bulk_in_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
/* wMaxPacketSize set by autoconfiguration */ /* wMaxPacketSize set by autoconfiguration */
}; };
EXPORT_SYMBOL(fsg_fs_bulk_in_desc);
static struct usb_endpoint_descriptor struct usb_endpoint_descriptor fsg_fs_bulk_out_desc = {
fsg_fs_bulk_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
...@@ -293,13 +73,15 @@ fsg_fs_bulk_out_desc = { ...@@ -293,13 +73,15 @@ fsg_fs_bulk_out_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
/* wMaxPacketSize set by autoconfiguration */ /* 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_intf_desc,
(struct usb_descriptor_header *) &fsg_fs_bulk_in_desc, (struct usb_descriptor_header *) &fsg_fs_bulk_in_desc,
(struct usb_descriptor_header *) &fsg_fs_bulk_out_desc, (struct usb_descriptor_header *) &fsg_fs_bulk_out_desc,
NULL, NULL,
}; };
EXPORT_SYMBOL(fsg_fs_function);
/* /*
...@@ -310,8 +92,7 @@ static struct usb_descriptor_header *fsg_fs_function[] = { ...@@ -310,8 +92,7 @@ static struct usb_descriptor_header *fsg_fs_function[] = {
* and a "device qualifier" ... plus more construction options * and a "device qualifier" ... plus more construction options
* for the configuration descriptor. * for the configuration descriptor.
*/ */
static struct usb_endpoint_descriptor struct usb_endpoint_descriptor fsg_hs_bulk_in_desc = {
fsg_hs_bulk_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
...@@ -319,9 +100,9 @@ fsg_hs_bulk_in_desc = { ...@@ -319,9 +100,9 @@ fsg_hs_bulk_in_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(512), .wMaxPacketSize = cpu_to_le16(512),
}; };
EXPORT_SYMBOL(fsg_hs_bulk_in_desc);
static struct usb_endpoint_descriptor struct usb_endpoint_descriptor fsg_hs_bulk_out_desc = {
fsg_hs_bulk_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
...@@ -330,17 +111,18 @@ fsg_hs_bulk_out_desc = { ...@@ -330,17 +111,18 @@ fsg_hs_bulk_out_desc = {
.wMaxPacketSize = cpu_to_le16(512), .wMaxPacketSize = cpu_to_le16(512),
.bInterval = 1, /* NAK every 1 uframe */ .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_intf_desc,
(struct usb_descriptor_header *) &fsg_hs_bulk_in_desc, (struct usb_descriptor_header *) &fsg_hs_bulk_in_desc,
(struct usb_descriptor_header *) &fsg_hs_bulk_out_desc, (struct usb_descriptor_header *) &fsg_hs_bulk_out_desc,
NULL, NULL,
}; };
EXPORT_SYMBOL(fsg_hs_function);
static struct usb_endpoint_descriptor struct usb_endpoint_descriptor fsg_ss_bulk_in_desc = {
fsg_ss_bulk_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
...@@ -348,16 +130,17 @@ fsg_ss_bulk_in_desc = { ...@@ -348,16 +130,17 @@ fsg_ss_bulk_in_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024), .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), .bLength = sizeof(fsg_ss_bulk_in_comp_desc),
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP, .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
/*.bMaxBurst = DYNAMIC, */ /*.bMaxBurst = DYNAMIC, */
}; };
EXPORT_SYMBOL(fsg_ss_bulk_in_comp_desc);
static struct usb_endpoint_descriptor struct usb_endpoint_descriptor fsg_ss_bulk_out_desc = {
fsg_ss_bulk_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
...@@ -365,15 +148,17 @@ fsg_ss_bulk_out_desc = { ...@@ -365,15 +148,17 @@ fsg_ss_bulk_out_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024), .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), .bLength = sizeof(fsg_ss_bulk_in_comp_desc),
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP, .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
/*.bMaxBurst = DYNAMIC, */ /*.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_intf_desc,
(struct usb_descriptor_header *) &fsg_ss_bulk_in_desc, (struct usb_descriptor_header *) &fsg_ss_bulk_in_desc,
(struct usb_descriptor_header *) &fsg_ss_bulk_in_comp_desc, (struct usb_descriptor_header *) &fsg_ss_bulk_in_comp_desc,
...@@ -381,17 +166,7 @@ static struct usb_descriptor_header *fsg_ss_function[] = { ...@@ -381,17 +166,7 @@ static struct usb_descriptor_header *fsg_ss_function[] = {
(struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc, (struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc,
NULL, NULL,
}; };
EXPORT_SYMBOL(fsg_ss_function);
/* 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,
};
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -401,7 +176,7 @@ static struct usb_gadget_strings fsg_stringtab = { ...@@ -401,7 +176,7 @@ static struct usb_gadget_strings fsg_stringtab = {
* the caller must own fsg->filesem for writing. * 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) { if (curlun->filp) {
LDBG(curlun, "close backing file\n"); LDBG(curlun, "close backing file\n");
...@@ -409,9 +184,9 @@ static void fsg_lun_close(struct fsg_lun *curlun) ...@@ -409,9 +184,9 @@ static void fsg_lun_close(struct fsg_lun *curlun)
curlun->filp = NULL; curlun->filp = NULL;
} }
} }
EXPORT_SYMBOL(fsg_lun_close);
int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
{ {
int ro; int ro;
struct file *filp = NULL; struct file *filp = NULL;
...@@ -508,6 +283,7 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) ...@@ -508,6 +283,7 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
fput(filp); fput(filp);
return rc; return rc;
} }
EXPORT_SYMBOL(fsg_lun_open);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -516,7 +292,7 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) ...@@ -516,7 +292,7 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
* Sync the file data, don't bother with the metadata. * Sync the file data, don't bother with the metadata.
* This code was copied from fs/buffer.c:sys_fdatasync(). * 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; struct file *filp = curlun->filp;
...@@ -524,8 +300,9 @@ static int fsg_lun_fsync_sub(struct fsg_lun *curlun) ...@@ -524,8 +300,9 @@ static int fsg_lun_fsync_sub(struct fsg_lun *curlun)
return 0; return 0;
return vfs_fsync(filp, 1); 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) { if (msf) {
/* Convert to Minutes-Seconds-Frames */ /* Convert to Minutes-Seconds-Frames */
...@@ -542,13 +319,13 @@ static void store_cdrom_address(u8 *dest, int msf, u32 addr) ...@@ -542,13 +319,13 @@ static void store_cdrom_address(u8 *dest, int msf, u32 addr)
put_unaligned_be32(addr, dest); put_unaligned_be32(addr, dest);
} }
} }
EXPORT_SYMBOL(store_cdrom_address);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static ssize_t ro_show(struct device *dev, struct device_attribute *attr, ssize_t fsg_show_ro(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct fsg_lun *curlun = fsg_lun_from_dev(dev); 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, ...@@ -556,17 +333,19 @@ static ssize_t ro_show(struct device *dev, struct device_attribute *attr,
? curlun->ro ? curlun->ro
: curlun->initially_ro); : curlun->initially_ro);
} }
EXPORT_SYMBOL(fsg_show_ro);
static ssize_t nofua_show(struct device *dev, struct device_attribute *attr, ssize_t fsg_show_nofua(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct fsg_lun *curlun = fsg_lun_from_dev(dev); struct fsg_lun *curlun = fsg_lun_from_dev(dev);
return sprintf(buf, "%u\n", curlun->nofua); return sprintf(buf, "%u\n", curlun->nofua);
} }
EXPORT_SYMBOL(fsg_show_nofua);
static ssize_t file_show(struct device *dev, struct device_attribute *attr, ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct fsg_lun *curlun = fsg_lun_from_dev(dev); struct fsg_lun *curlun = fsg_lun_from_dev(dev);
struct rw_semaphore *filesem = dev_get_drvdata(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, ...@@ -591,10 +370,11 @@ static ssize_t file_show(struct device *dev, struct device_attribute *attr,
up_read(filesem); up_read(filesem);
return rc; return rc;
} }
EXPORT_SYMBOL(fsg_show_file);
static ssize_t ro_store(struct device *dev, struct device_attribute *attr, ssize_t fsg_store_ro(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
ssize_t rc; ssize_t rc;
struct fsg_lun *curlun = fsg_lun_from_dev(dev); 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, ...@@ -622,9 +402,10 @@ static ssize_t ro_store(struct device *dev, struct device_attribute *attr,
up_read(filesem); up_read(filesem);
return rc; return rc;
} }
EXPORT_SYMBOL(fsg_store_ro);
static ssize_t nofua_store(struct device *dev, struct device_attribute *attr, ssize_t fsg_store_nofua(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct fsg_lun *curlun = fsg_lun_from_dev(dev); struct fsg_lun *curlun = fsg_lun_from_dev(dev);
unsigned nofua; unsigned nofua;
...@@ -642,9 +423,10 @@ static ssize_t nofua_store(struct device *dev, struct device_attribute *attr, ...@@ -642,9 +423,10 @@ static ssize_t nofua_store(struct device *dev, struct device_attribute *attr,
return count; return count;
} }
EXPORT_SYMBOL(fsg_store_nofua);
static ssize_t file_store(struct device *dev, struct device_attribute *attr, ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct fsg_lun *curlun = fsg_lun_from_dev(dev); struct fsg_lun *curlun = fsg_lun_from_dev(dev);
struct rw_semaphore *filesem = dev_get_drvdata(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, ...@@ -674,3 +456,6 @@ static ssize_t file_store(struct device *dev, struct device_attribute *attr,
up_write(filesem); up_write(filesem);
return (rc < 0 ? rc : count); return (rc < 0 ? rc : count);
} }
EXPORT_SYMBOL(fsg_store_file);
MODULE_LICENSE("GPL");
#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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment