diff options
author | John Stultz <john.stultz@linaro.org> | 2013-11-26 14:17:46 -0800 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2013-11-26 14:17:46 -0800 |
commit | 8c4f8fd63c807039d4c2e92ba754a20aee8e1bd4 (patch) | |
tree | 1c413874604cc1b7272078a15e5c33bfe35f290c | |
parent | d007df1451226a418fa57e1a06edb2439f04387d (diff) |
android gadget: mass storage merge fixups for 3.13-rc1tracking-linaro-android-3.13-llct-20131211.0tracking-linaro-android-3.13-llct-20131209.0tracking-linaro-android-3.13-llct-20131206.0tracking-linaro-android-3.13-llct-20131204.0tracking-linaro-android-3.13-llct-20131202.0tracking-linaro-android-3.13-llct-20131129.0tracking-linaro-android-3.13-llct-20131128.0
Lots of change in the 3.13-rc1 mass storage gadget function caused
some havvoc on the android gadget driver. I tried to reimplement
this following the ACM function, but no promises that I got it right.
Currently untested.
Signed-off-by: John Stultz <john.stultz@linaro.org>
-rw-r--r-- | drivers/usb/gadget/Kconfig | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/android.c | 149 |
2 files changed, 98 insertions, 53 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 1f0fe8c7e64f..4f123d933b13 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -990,6 +990,8 @@ config USB_G_ANDROID select USB_F_ACM select USB_LIBCOMPOSITE select USB_U_SERIAL + select USB_F_MASS_STORAGE + select SND_PCM help The Android Composite Gadget supports multiple USB functions: adb, acm, mass storage, mtp, accessory diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c index fc34f68bc4fe..138c6172877c 100644 --- a/drivers/usb/gadget/android.c +++ b/drivers/usb/gadget/android.c @@ -32,7 +32,6 @@ #include "f_fs.c" #include "f_audio_source.c" -#include "f_mass_storage.c" #include "f_mtp.c" #include "f_accessory.c" #define USB_ETH_RNDIS y @@ -750,93 +749,137 @@ static struct android_usb_function rndis_function = { }; -struct mass_storage_function_config { - struct fsg_config fsg; - struct fsg_common *common; +#define MAX_MS_INSTANCES 1 +struct ms_function_config { + int instances; + int instances_on; + struct usb_function *f_ms[MAX_MS_INSTANCES]; + struct usb_function_instance *f_ms_inst[MAX_MS_INSTANCES]; }; -static int mass_storage_function_init(struct android_usb_function *f, - struct usb_composite_dev *cdev) +static int +ms_function_init(struct android_usb_function *f, + struct usb_composite_dev *cdev) { - struct mass_storage_function_config *config; - struct fsg_common *common; - int err; + int i; + int ret; + struct ms_function_config *config; - config = kzalloc(sizeof(struct mass_storage_function_config), - GFP_KERNEL); + config = kzalloc(sizeof(struct ms_function_config), GFP_KERNEL); if (!config) return -ENOMEM; + f->config = config; - config->fsg.nluns = 1; - config->fsg.luns[0].removable = 1; - - common = fsg_common_init(NULL, cdev, &config->fsg); - if (IS_ERR(common)) { - kfree(config); - return PTR_ERR(common); - } - - err = sysfs_create_link(&f->dev->kobj, - &common->luns[0].dev.kobj, - "lun"); - if (err) { - kfree(config); - return err; + for (i = 0; i < MAX_MS_INSTANCES; i++) { + config->f_ms_inst[i] = usb_get_function_instance("mass_storage"); + if (IS_ERR(config->f_ms_inst[i])) { + ret = PTR_ERR(config->f_ms_inst[i]); + goto err_usb_get_function_instance; + } + config->f_ms[i] = usb_get_function(config->f_ms_inst[i]); + if (IS_ERR(config->f_ms[i])) { + ret = PTR_ERR(config->f_ms[i]); + goto err_usb_get_function; + } } - - config->common = common; - f->config = config; return 0; +err_usb_get_function_instance: + while (i-- > 0) { + usb_put_function(config->f_ms[i]); +err_usb_get_function: + usb_put_function_instance(config->f_ms_inst[i]); + } + return ret; } -static void mass_storage_function_cleanup(struct android_usb_function *f) +static void ms_function_cleanup(struct android_usb_function *f) { + int i; + struct ms_function_config *config = f->config; + + for (i = 0; i < MAX_MS_INSTANCES; i++) { + usb_put_function(config->f_ms[i]); + usb_put_function_instance(config->f_ms_inst[i]); + } kfree(f->config); f->config = NULL; } -static int mass_storage_function_bind_config(struct android_usb_function *f, - struct usb_configuration *c) +static int +ms_function_bind_config(struct android_usb_function *f, + struct usb_configuration *c) +{ + int i; + int ret = 0; + struct ms_function_config *config = f->config; + + config->instances_on = config->instances; + for (i = 0; i < config->instances_on; i++) { + ret = usb_add_function(c, config->f_ms[i]); + if (ret) { + pr_err("Could not bind ms%u config\n", i); + goto err_usb_add_function; + } + } + + return 0; + +err_usb_add_function: + while (i-- > 0) + usb_remove_function(c, config->f_ms[i]); + return ret; +} + +static void ms_function_unbind_config(struct android_usb_function *f, + struct usb_configuration *c) { - struct mass_storage_function_config *config = f->config; - return fsg_bind_config(c->cdev, c, config->common); + int i; + struct ms_function_config *config = f->config; + + for (i = 0; i < config->instances_on; i++) + usb_remove_function(c, config->f_ms[i]); } -static ssize_t mass_storage_inquiry_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t ms_inquiry_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct android_usb_function *f = dev_get_drvdata(dev); - struct mass_storage_function_config *config = f->config; - return sprintf(buf, "%s\n", config->common->inquiry_string); + struct ms_function_config *config = f->config; + return sprintf(buf, "%d\n", config->instances); } -static ssize_t mass_storage_inquiry_store(struct device *dev, +static ssize_t ms_inquiry_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct android_usb_function *f = dev_get_drvdata(dev); - struct mass_storage_function_config *config = f->config; - if (size >= sizeof(config->common->inquiry_string)) - return -EINVAL; - if (sscanf(buf, "%s", config->common->inquiry_string) != 1) - return -EINVAL; + struct ms_function_config *config = f->config; + int value; + + sscanf(buf, "%d", &value); + if (value > MAX_MS_INSTANCES) + value = MAX_MS_INSTANCES; + config->instances = value; return size; } static DEVICE_ATTR(inquiry_string, S_IRUGO | S_IWUSR, - mass_storage_inquiry_show, - mass_storage_inquiry_store); + ms_inquiry_show, + ms_inquiry_store); -static struct device_attribute *mass_storage_function_attributes[] = { +static struct device_attribute *ms_function_attributes[] = { &dev_attr_inquiry_string, NULL }; -static struct android_usb_function mass_storage_function = { + + +static struct android_usb_function ms_function = { .name = "mass_storage", - .init = mass_storage_function_init, - .cleanup = mass_storage_function_cleanup, - .bind_config = mass_storage_function_bind_config, - .attributes = mass_storage_function_attributes, + .init = ms_function_init, + .cleanup = ms_function_cleanup, + .bind_config = ms_function_bind_config, + .unbind_config = ms_function_unbind_config, + .attributes = ms_function_attributes, }; @@ -940,7 +983,7 @@ static struct android_usb_function *supported_functions[] = { &mtp_function, &ptp_function, &rndis_function, - &mass_storage_function, + &ms_function, &accessory_function, &audio_source_function, NULL |