diff options
author | Benn Pörscke <benn.porscke@stericsson.com> | 2011-10-07 15:31:57 +0200 |
---|---|---|
committer | Benn Pörscke <benn.porscke@stericsson.com> | 2011-10-07 15:31:57 +0200 |
commit | 47a4dbf83a75014d6b3467be18997894f1c617db (patch) | |
tree | 7f5d116db48205309fbc4ae0954f20ab8a651e46 /drivers/usb/gadget/f_mass_storage.c | |
parent | ea8a52f9f4bcc3420c38ae07f8378a2f18443970 (diff) |
Squashandroid-20111012
Change-Id: If0ae9fa8067740ab2ede33703c79ec134f204a5e
Diffstat (limited to 'drivers/usb/gadget/f_mass_storage.c')
-rw-r--r-- | drivers/usb/gadget/f_mass_storage.c | 157 |
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 */ + |