summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/f_mass_storage.c
diff options
context:
space:
mode:
authorBenn Pörscke <benn.porscke@stericsson.com>2011-10-07 15:31:57 +0200
committerBenn Pörscke <benn.porscke@stericsson.com>2011-10-07 15:31:57 +0200
commit47a4dbf83a75014d6b3467be18997894f1c617db (patch)
tree7f5d116db48205309fbc4ae0954f20ab8a651e46 /drivers/usb/gadget/f_mass_storage.c
parentea8a52f9f4bcc3420c38ae07f8378a2f18443970 (diff)
Change-Id: If0ae9fa8067740ab2ede33703c79ec134f204a5e
Diffstat (limited to 'drivers/usb/gadget/f_mass_storage.c')
-rw-r--r--drivers/usb/gadget/f_mass_storage.c157
1 files changed, 113 insertions, 44 deletions
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 4ce899c9b16..1a08f15c4b8 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -295,7 +295,12 @@
#include "gadget_chips.h"
+#ifdef CONFIG_USB_ANDROID_MASS_STORAGE
+#include <linux/usb/android_composite.h>
+#include <linux/platform_device.h>
+#define FUNCTION_NAME "usb_mass_storage"
+#endif
/*------------------------------------------------------------------------*/
@@ -408,6 +413,10 @@ struct fsg_config {
u16 release;
char can_stall;
+
+#ifdef CONFIG_USB_ANDROID_MASS_STORAGE
+ struct platform_device *pdev;
+#endif
};
@@ -454,19 +463,6 @@ static int exception_in_progress(struct fsg_common *common)
return common->state > FSG_STATE_IDLE;
}
-/* 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)
-{
- unsigned int rem;
-
- bh->bulk_out_intended_length = length;
- rem = length % common->bulk_out_maxpacket;
- if (rem > 0)
- length += common->bulk_out_maxpacket - rem;
- bh->outreq->length = length;
-}
-
/*-------------------------------------------------------------------------*/
static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
@@ -564,10 +560,9 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
struct fsg_buffhd *bh = req->context;
dump_msg(common, "bulk-out", req->buf, req->actual);
- if (req->status || req->actual != bh->bulk_out_intended_length)
+ if (req->status || req->actual != req->length)
DBG(common, "%s --> %d, %u/%u\n", __func__,
- req->status, req->actual,
- bh->bulk_out_intended_length);
+ req->status, req->actual, req->length);
if (req->status == -ECONNRESET) /* Request was cancelled */
usb_ep_fifo_flush(ep);
@@ -609,6 +604,7 @@ static int fsg_setup(struct usb_function *f,
/* Raise an exception to stop the current operation
* and reinitialize our state. */
DBG(fsg, "bulk reset request\n");
+ fsg->common->ep0req->length = 0;
raise_exception(fsg->common, FSG_STATE_RESET);
return DELAYED_STATUS;
@@ -939,7 +935,6 @@ static int do_write(struct fsg_common *common)
/* amount is always divisible by 512, hence by
* the bulk-out maxpacket size */
bh->outreq->length = amount;
- bh->bulk_out_intended_length = amount;
bh->outreq->short_not_ok = 1;
START_TRANSFER_OR(common, bulk_out, bh->outreq,
&bh->outreq_busy, &bh->state)
@@ -1343,30 +1338,7 @@ static int do_mode_sense(struct fsg_common *common, struct fsg_buffhd *bh)
limit = 65535; /* Should really be FSG_BUFLEN */
}
- /* No block descriptors */
-
- /* The mode pages, in numerical order. The only page we support
- * is the Caching page. */
- if (page_code == 0x08 || all_pages) {
- valid_page = 1;
- buf[0] = 0x08; /* Page code */
- buf[1] = 10; /* Page length */
- memset(buf+2, 0, 10); /* None of the fields are changeable */
-
- if (!changeable_values) {
- buf[2] = 0x04; /* Write cache enable, */
- /* Read cache not disabled */
- /* No cache retention priorities */
- put_unaligned_be16(0xffff, &buf[4]);
- /* Don't disable prefetch */
- /* Minimum prefetch = 0 */
- put_unaligned_be16(0xffff, &buf[8]);
- /* Maximum prefetch */
- put_unaligned_be16(0xffff, &buf[10]);
- /* Maximum prefetch ceiling */
- }
- buf += 12;
- }
+ valid_page = 1;
/* Check that a valid page was requested and the mode data length
* isn't too long. */
@@ -1602,7 +1574,6 @@ static int throw_away_data(struct fsg_common *common)
/* amount is always divisible by 512, hence by
* the bulk-out maxpacket size */
bh->outreq->length = amount;
- bh->bulk_out_intended_length = amount;
bh->outreq->short_not_ok = 1;
START_TRANSFER_OR(common, bulk_out, bh->outreq,
&bh->outreq_busy, &bh->state)
@@ -2253,8 +2224,8 @@ static int get_next_command(struct fsg_common *common)
}
/* Queue a request to read a Bulk-only CBW */
- set_bulk_out_req_length(common, bh, USB_BULK_CB_WRAP_LEN);
- bh->outreq->short_not_ok = 1;
+ bh->outreq->length = USB_BULK_CB_WRAP_LEN;
+ bh->outreq->short_not_ok = 0;
START_TRANSFER_OR(common, bulk_out, bh->outreq,
&bh->outreq_busy, &bh->state)
/* Don't know what to do if common->fsg is NULL */
@@ -2717,7 +2688,13 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
curlun->ro = lcfg->cdrom || lcfg->ro;
curlun->removable = lcfg->removable;
curlun->dev.release = fsg_lun_release;
+
+#ifdef CONFIG_USB_ANDROID_MASS_STORAGE
+ /* use "usb_mass_storage" platform device as parent */
+ curlun->dev.parent = &cfg->pdev->dev;
+#else
curlun->dev.parent = &gadget->dev;
+#endif
/* curlun->dev.driver = &fsg_driver.driver; XXX */
dev_set_drvdata(&curlun->dev, &common->filesem);
dev_set_name(&curlun->dev,
@@ -3001,7 +2978,11 @@ static int fsg_add(struct usb_composite_dev *cdev,
if (unlikely(!fsg))
return -ENOMEM;
+#ifdef CONFIG_USB_ANDROID_MASS_STORAGE
+ fsg->function.name = FUNCTION_NAME;
+#else
fsg->function.name = FSG_DRIVER_DESC;
+#endif
fsg->function.strings = fsg_strings_array;
fsg->function.bind = fsg_bind;
fsg->function.unbind = fsg_unbind;
@@ -3118,3 +3099,91 @@ fsg_common_from_params(struct fsg_common *common,
return fsg_common_init(common, cdev, &cfg);
}
+#ifdef CONFIG_USB_ANDROID_MASS_STORAGE
+
+static struct fsg_config fsg_cfg;
+
+static int fsg_probe(struct platform_device *pdev)
+{
+ struct usb_mass_storage_platform_data *pdata = pdev->dev.platform_data;
+ int i, nluns;
+
+ printk(KERN_INFO "fsg_probe pdev: %p, pdata: %p\n", pdev, pdata);
+ if (!pdata)
+ return -1;
+
+ nluns = pdata->nluns;
+ if (nluns > FSG_MAX_LUNS)
+ nluns = FSG_MAX_LUNS;
+ fsg_cfg.nluns = nluns;
+ for (i = 0; i < nluns; i++)
+ fsg_cfg.luns[i].removable = 1;
+
+ fsg_cfg.vendor_name = pdata->vendor;
+ fsg_cfg.product_name = pdata->product;
+ fsg_cfg.release = pdata->release;
+ fsg_cfg.can_stall = 0;
+ fsg_cfg.pdev = pdev;
+
+ return 0;
+}
+
+static struct platform_driver fsg_platform_driver = {
+ .driver = { .name = FUNCTION_NAME, },
+ .probe = fsg_probe,
+};
+
+int mass_storage_bind_config(struct usb_configuration *c)
+{
+ struct fsg_common *common = fsg_common_init(NULL, c->cdev, &fsg_cfg);
+ if (IS_ERR(common))
+ return -1;
+ return fsg_add(c->cdev, c, common);
+}
+
+static int mass_storage_rebind_config(struct usb_configuration *c,
+ struct usb_function *f)
+{
+ struct fsg_dev *fsg = fsg_from_func(f);
+ struct usb_gadget *gadget = c->cdev->gadget;
+ int i;
+
+ fsg->gadget = gadget;
+
+ /* New interface */
+ i = usb_interface_id(c, f);
+ if (i < 0)
+ return i;
+ fsg_intf_desc.bInterfaceNumber = i;
+ fsg->interface_number = i;
+
+#ifndef FSG_NO_OTG
+ ((struct usb_interface_assoc_descriptor *)f->descriptors[1]
+ ->bFirstInterface = i;
+#else
+ ((struct usb_interface_assoc_descriptor *)f->descriptors[0])
+ ->bFirstInterface = i;
+#endif
+
+ return 0;
+}
+
+static struct android_usb_function mass_storage_function = {
+ .name = FUNCTION_NAME,
+ .bind_config = mass_storage_bind_config,
+ .rebind_config = mass_storage_rebind_config,
+};
+
+static int __init init(void)
+{
+ int rc;
+ printk(KERN_INFO "f_mass_storage init\n");
+ rc = platform_driver_register(&fsg_platform_driver);
+ if (rc != 0)
+ return rc;
+ android_register_function(&mass_storage_function);
+ return 0;
+}module_init(init);
+
+#endif /* CONFIG_USB_ANDROID_MASS_STORAGE */
+