aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2014-03-28 16:32:33 -0700
committerJohn Stultz <john.stultz@linaro.org>2014-03-28 17:05:53 -0700
commit47f51bdd492879ef89b9016ad2b288faf0a70bcc (patch)
tree911ccf3332545cdf1d07b856dda0ba4678b4b811
parente2ef3735b676024a6771497a15bf4b45f0cf4f68 (diff)
Here are some of the build fixes we're using at Linaro. I suspect much of this is incorrect, but wanted to submit it as a starting place to get things fixed. Change-Id: Id471d3004eef2aa2a6317950f434ad2b549b9dfc Signed-off-by: John Stultz <john.stultz@linaro.org>
-rw-r--r--drivers/usb/gadget/Kconfig2
-rw-r--r--drivers/usb/gadget/android.c101
-rw-r--r--drivers/usb/gadget/f_fs.c90
-rw-r--r--drivers/usb/gadget/f_rndis.c56
4 files changed, 219 insertions, 30 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index e272b648d329..d8e4660faf47 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -1024,6 +1024,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 a74ae6b26ea9..91f0efdabc8a 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
@@ -40,6 +39,8 @@
#include "rndis.c"
#include "u_ether.c"
+USB_ETHERNET_MODULE_PARAMETERS();
+
MODULE_AUTHOR("Mike Lockwood");
MODULE_DESCRIPTION("Android Composite USB Driver");
MODULE_LICENSE("GPL");
@@ -596,7 +597,7 @@ rndis_function_bind_config(struct android_usb_function *f,
rndis->ethaddr[0], rndis->ethaddr[1], rndis->ethaddr[2],
rndis->ethaddr[3], rndis->ethaddr[4], rndis->ethaddr[5]);
- dev = gether_setup_name(c->cdev->gadget, rndis->ethaddr, "rndis");
+ dev = gether_setup_name(c->cdev->gadget,dev_addr, host_addr, rndis->ethaddr, qmult, "rndis");
if (IS_ERR(dev)) {
ret = PTR_ERR(dev);
pr_err("%s: gether_setup failed\n", __func__);
@@ -746,47 +747,58 @@ static struct android_usb_function rndis_function = {
};
+#define MAX_MS_INSTANCES 1
struct mass_storage_function_config {
- struct fsg_config fsg;
- struct fsg_common *common;
+ 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)
{
struct mass_storage_function_config *config;
- struct fsg_common *common;
- int err;
+ int i;
+ int ret;
config = kzalloc(sizeof(struct mass_storage_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)
{
+ struct mass_storage_function_config *config = f->config;
+ int i;
+
+ 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;
}
@@ -795,7 +807,34 @@ static int mass_storage_function_bind_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 ret = 0;
+ int i;
+
+ 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 mass_storage_function_unbind_config(struct android_usb_function *f,
+ struct usb_configuration *c)
+{
+ int i;
+ struct mass_storage_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,
@@ -803,7 +842,7 @@ static ssize_t mass_storage_inquiry_show(struct device *dev,
{
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);
+ return sprintf(buf, "%d\n", config->instances);
}
static ssize_t mass_storage_inquiry_store(struct device *dev,
@@ -811,10 +850,12 @@ static ssize_t mass_storage_inquiry_store(struct device *dev,
{
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;
+ int value;
+
+ sscanf(buf, "%d", &value);
+ if (value > MAX_MS_INSTANCES)
+ value = MAX_MS_INSTANCES;
+ config->instances = value;
return size;
}
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index 663078c0dafe..ebbae4667b11 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -98,12 +98,15 @@ static struct ffs_function *ffs_func_from_usb(struct usb_function *f)
return container_of(f, struct ffs_function, function);
}
+static void ffs_func_free(struct ffs_function *func);
static void ffs_func_eps_disable(struct ffs_function *func);
static int __must_check ffs_func_eps_enable(struct ffs_function *func);
static int ffs_func_bind(struct usb_configuration *,
struct usb_function *);
+static void old_ffs_func_unbind(struct usb_configuration *,
+ struct usb_function *);
static int ffs_func_set_alt(struct usb_function *, unsigned, unsigned);
static void ffs_func_disable(struct usb_function *);
static int ffs_func_setup(struct usb_function *,
@@ -1302,6 +1305,73 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count)
}
+static int functionfs_bind_config(struct usb_composite_dev *cdev,
+ struct usb_configuration *c,
+ struct ffs_data *ffs)
+{
+ struct ffs_function *func;
+ int ret;
+
+ ENTER();
+
+ func = kzalloc(sizeof *func, GFP_KERNEL);
+ if (unlikely(!func))
+ return -ENOMEM;
+
+ func->function.name = "Function FS Gadget";
+ func->function.strings = ffs->stringtabs;
+
+ func->function.bind = ffs_func_bind;
+ func->function.unbind = old_ffs_func_unbind;
+ func->function.set_alt = ffs_func_set_alt;
+ func->function.disable = ffs_func_disable;
+ func->function.setup = ffs_func_setup;
+ func->function.suspend = ffs_func_suspend;
+ func->function.resume = ffs_func_resume;
+
+ func->conf = c;
+ func->gadget = cdev->gadget;
+ func->ffs = ffs;
+ ffs_data_get(ffs);
+
+ ret = usb_add_function(c, &func->function);
+ if (unlikely(ret))
+ ffs_func_free(func);
+
+ return ret;
+}
+
+static void ffs_func_free(struct ffs_function *func)
+{
+ struct ffs_ep *ep = func->eps;
+ unsigned count = func->ffs->eps_count;
+ unsigned long flags;
+
+ ENTER();
+
+ /* cleanup after autoconfig */
+ spin_lock_irqsave(&func->ffs->eps_lock, flags);
+ do {
+ if (ep->ep && ep->req)
+ usb_ep_free_request(ep->ep, ep->req);
+ ep->req = NULL;
+ ++ep;
+ } while (--count);
+ spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
+
+ ffs_data_put(func->ffs);
+
+ kfree(func->eps);
+ /*
+ * eps and interfaces_nums are allocated in the same chunk so
+ * only one free is required. Descriptors are also allocated
+ * in the same chunk.
+ */
+
+ kfree(func);
+}
+
+
static void ffs_func_eps_disable(struct ffs_function *func)
{
struct ffs_ep *ep = func->eps;
@@ -2133,6 +2203,26 @@ static int ffs_func_bind(struct usb_configuration *c,
/* Other USB function hooks *************************************************/
+
+static void old_ffs_func_unbind(struct usb_configuration *c,
+ struct usb_function *f)
+{
+ struct ffs_function *func = ffs_func_from_usb(f);
+ struct ffs_data *ffs = func->ffs;
+
+ ENTER();
+
+ if (ffs->func == func) {
+ ffs_func_eps_disable(func);
+ ffs->func = NULL;
+ }
+
+ ffs_event_add(ffs, FUNCTIONFS_UNBIND);
+
+ ffs_func_free(func);
+}
+
+
static int ffs_func_set_alt(struct usb_function *f,
unsigned interface, unsigned alt)
{
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index c11761ce5113..a3a220890b58 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -822,6 +822,62 @@ fail:
return status;
}
+static void
+rndis_old_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct f_rndis *rndis = func_to_rndis(f);
+
+ rndis_deregister(rndis->config);
+
+ usb_free_all_descriptors(f);
+
+ kfree(rndis->notify_req->buf);
+ usb_ep_free_request(rndis->notify, rndis->notify_req);
+
+ kfree(rndis);
+}
+
+int
+rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+ u32 vendorID, const char *manufacturer, struct eth_dev *dev)
+{
+ struct f_rndis *rndis;
+ int status;
+
+ /* allocate and initialize one new instance */
+ status = -ENOMEM;
+ rndis = kzalloc(sizeof *rndis, GFP_KERNEL);
+ if (!rndis)
+ goto fail;
+
+ memcpy(rndis->ethaddr, ethaddr, ETH_ALEN);
+ rndis->vendorID = vendorID;
+ rndis->manufacturer = manufacturer;
+
+ rndis->port.ioport = dev;
+ /* RNDIS activates when the host changes this filter */
+ rndis->port.cdc_filter = 0;
+
+ /* RNDIS has special (and complex) framing */
+ rndis->port.header_len = sizeof(struct rndis_packet_msg_type);
+ rndis->port.wrap = rndis_add_header;
+ rndis->port.unwrap = rndis_rm_hdr;
+
+ rndis->port.func.name = "rndis";
+ /* descriptors are per-instance copies */
+ rndis->port.func.bind = rndis_bind;
+ rndis->port.func.unbind = rndis_old_unbind;
+ rndis->port.func.set_alt = rndis_set_alt;
+ rndis->port.func.setup = rndis_setup;
+ rndis->port.func.disable = rndis_disable;
+
+ status = usb_add_function(c, &rndis->port.func);
+ if (status)
+ kfree(rndis);
+fail:
+ return status;
+}
+
void rndis_borrow_net(struct usb_function_instance *f, struct net_device *net)
{
struct f_rndis_opts *opts;