aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2014-03-03 18:38:58 -0800
committerJohn Stultz <john.stultz@linaro.org>2014-03-03 18:38:58 -0800
commit5694c36033aeb07b41862ada4d8c3df053d72afa (patch)
treec07cebb8c99981fca8426d444693fadba4454786
parent3e822390c4c3d4cbc6319f17080532ecdc07b360 (diff)
Some of the functionfs and rdnis ethernet gadget changes in 3.14 removed interfaces the Android gadget depends on. This patch re-adds those interfaces to make things build. Signed-off-by: John Stultz <john.stultz@linaro.org>
-rw-r--r--drivers/usb/gadget/f_fs.c106
-rw-r--r--drivers/usb/gadget/f_rndis.c72
-rw-r--r--drivers/usb/gadget/u_ether.h36
-rw-r--r--drivers/usb/gadget/u_fs.h2
-rw-r--r--include/linux/usb/functionfs.h18
5 files changed, 233 insertions, 1 deletions
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index 663078c0dafe..66e02a672a50 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 *,
@@ -159,7 +162,9 @@ ffs_sb_create_file(struct super_block *sb, const char *name, void *data,
/* Devices management *******************************************************/
DEFINE_MUTEX(ffs_lock);
+#ifndef USB_FFS_INCLUDED
EXPORT_SYMBOL(ffs_lock);
+#endif
static struct ffs_dev *ffs_find_dev(const char *name);
static int _ffs_name_dev(struct ffs_dev *dev, const char *name);
@@ -1302,6 +1307,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;
@@ -1969,6 +2041,7 @@ static int __ffs_func_bind_do_nums(enum ffs_entity_type type, u8 *valuep,
return 0;
}
+#ifndef USB_FFS_INCLUDED
static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f,
struct usb_configuration *c)
{
@@ -2017,6 +2090,7 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f,
return ffs_opts;
}
+#endif
static int _ffs_func_bind(struct usb_configuration *c,
struct usb_function *f)
@@ -2122,10 +2196,12 @@ error:
static int ffs_func_bind(struct usb_configuration *c,
struct usb_function *f)
{
+#ifndef USB_FFS_INCLUDED
struct f_fs_opts *ffs_opts = ffs_do_functionfs_bind(f, c);
if (IS_ERR(ffs_opts))
return PTR_ERR(ffs_opts);
+#endif
return _ffs_func_bind(c, f);
}
@@ -2133,6 +2209,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)
{
@@ -2334,6 +2430,8 @@ static struct config_item_type ffs_func_type = {
/* Function registration interface ******************************************/
+#ifndef USB_FFS_INCLUDED
+
static void ffs_free_inst(struct usb_function_instance *f)
{
struct f_fs_opts *opts;
@@ -2480,6 +2578,8 @@ static struct usb_function *ffs_alloc(struct usb_function_instance *fi)
return &func->function;
}
+#endif
+
/*
* ffs_lock must be taken by the caller of this function
*/
@@ -2538,7 +2638,9 @@ int ffs_name_dev(struct ffs_dev *dev, const char *name)
return ret;
}
+#ifndef USB_FFS_INCLUDED
EXPORT_SYMBOL(ffs_name_dev);
+#endif
int ffs_single_dev(struct ffs_dev *dev)
{
@@ -2555,7 +2657,9 @@ int ffs_single_dev(struct ffs_dev *dev)
ffs_dev_unlock();
return ret;
}
+#ifndef USB_FFS_INCLUDED
EXPORT_SYMBOL(ffs_single_dev);
+#endif
/*
* ffs_lock must be taken by the caller of this function
@@ -2695,6 +2799,8 @@ static char *ffs_prepare_buffer(const char __user *buf, size_t len)
return data;
}
+#ifndef USB_FFS_INCLUDED
DECLARE_USB_FUNCTION_INIT(ffs, ffs_alloc_inst, ffs_alloc);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Michal Nazarewicz");
+#endif
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index c11761ce5113..04a47b47cf35 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -675,6 +675,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
int status;
struct usb_ep *ep;
+#ifndef USB_FRNDIS_INCLUDED
struct f_rndis_opts *rndis_opts;
if (!can_support_rndis(c))
@@ -696,7 +697,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
return status;
rndis_opts->bound = true;
}
-
+#endif
us = usb_gstrings_attach(cdev, rndis_strings,
ARRAY_SIZE(rndis_string_defs));
if (IS_ERR(us))
@@ -781,6 +782,13 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
rndis->port.open = rndis_open;
rndis->port.close = rndis_close;
+#ifdef USB_FRNDIS_INCLUDED
+ status = rndis_register(rndis_response_available, rndis);
+ if (status < 0)
+ goto fail;
+ rndis->config = status;
+#endif
+
rndis_set_param_medium(rndis->config, RNDIS_MEDIUM_802_3, 0);
rndis_set_host_mac(rndis->config, rndis->ethaddr);
@@ -822,6 +830,66 @@ fail:
return status;
}
+#ifdef USB_FRNDIS_INCLUDED
+
+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;
+}
+
+#else
+
void rndis_borrow_net(struct usb_function_instance *f, struct net_device *net)
{
struct f_rndis_opts *opts;
@@ -1002,3 +1070,5 @@ module_exit(rndis_mod_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Brownell");
+
+#endif
diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h
index 0f0290acea7e..72b6facde40d 100644
--- a/drivers/usb/gadget/u_ether.h
+++ b/drivers/usb/gadget/u_ether.h
@@ -267,4 +267,40 @@ static inline bool can_support_ecm(struct usb_gadget *gadget)
return true;
}
+/* each configuration may bind one instance of an ethernet link */
+#ifdef USB_ETH_RNDIS
+
+int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+ u32 vendorID, const char *manufacturer, struct eth_dev *dev);
+
+#else
+
+static inline int
+rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+ u32 vendorID, const char *manufacturer, struct eth_dev *dev)
+{
+ return 0;
+}
+
+#endif
+
+/**
+ * rndis_bind_config - add RNDIS network link to a configuration
+ * @c: the configuration to support the network link
+ * @ethaddr: a buffer in which the ethernet address of the host side
+ * side of the link was recorded
+ * Context: single threaded during gadget setup
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * Caller must have called @gether_setup(). Caller is also responsible
+ * for calling @gether_cleanup() before module unload.
+ */
+static inline int rndis_bind_config(struct usb_configuration *c,
+ u8 ethaddr[ETH_ALEN], struct eth_dev *dev)
+{
+ return rndis_bind_config_vendor(c, ethaddr, 0, NULL, dev);
+}
+
+
#endif /* __U_ETHER_H */
diff --git a/drivers/usb/gadget/u_fs.h b/drivers/usb/gadget/u_fs.h
index bc2d3718219b..16261cd02f64 100644
--- a/drivers/usb/gadget/u_fs.h
+++ b/drivers/usb/gadget/u_fs.h
@@ -252,6 +252,7 @@ struct ffs_data {
};
+#ifndef USB_FFS_INCLUDED
struct f_fs_opts {
struct usb_function_instance func_inst;
struct ffs_dev *dev;
@@ -263,5 +264,6 @@ static inline struct f_fs_opts *to_f_fs_opts(struct usb_function_instance *fi)
{
return container_of(fi, struct f_fs_opts, func_inst);
}
+#endif
#endif /* U_FFS_H */
diff --git a/include/linux/usb/functionfs.h b/include/linux/usb/functionfs.h
index 71190663f1ee..3448efbe56aa 100644
--- a/include/linux/usb/functionfs.h
+++ b/include/linux/usb/functionfs.h
@@ -3,4 +3,22 @@
#include <uapi/linux/usb/functionfs.h>
+#ifdef USB_FFS_INCLUDED
+
+struct ffs_data;
+struct usb_composite_dev;
+struct usb_configuration;
+
+static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev)
+ __attribute__((warn_unused_result, nonnull));
+static void functionfs_unbind(struct ffs_data *ffs)
+ __attribute__((nonnull));
+
+static int functionfs_bind_config(struct usb_composite_dev *cdev,
+ struct usb_configuration *c,
+ struct ffs_data *ffs)
+ __attribute__((warn_unused_result, nonnull));
+
+
+#endif
#endif