Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0fdc146d authored by Amit Pundir's avatar Amit Pundir
Browse files

HACK: usb: gadget: fix android composite driver build



Even though Android is moving away from usb compsite gadget
driver to  ConfigFS gadgets, plan is to provide backward
compatibility to some extent.

This patch is a set of build fixes we're using at Linaro for
broken Android composite driver. I suspect much of this is
incorrect, but wanted to submit it as a starting place to
get things fixed and hopefully be able to get atleast ADB
working with this legacy Android composite gadget driver.

Signed-off-by: default avatarAmit Pundir <amit.pundir@linaro.org>
parent e9f6fb70
Loading
Loading
Loading
Loading
+0 −18
Original line number Diff line number Diff line
@@ -410,24 +410,6 @@ config USB_CONFIGFS_UEVENT
	  state changes. The gadget can be in any of the following
	  three states: "CONNECTED/DISCONNECTED/CONFIGURED"

config USB_G_ANDROID
	boolean "Android Composite Gadget"
	select USB_F_ACM
	select USB_LIBCOMPOSITE
	select USB_U_SERIAL
	help
	  The Android Composite Gadget supports multiple USB
	  functions: adb, acm, mass storage, mtp, accessory
	  and rndis.
	  Each function can be configured and enabled/disabled
	  dynamically from userspace through a sysfs interface.

config USB_ANDROID_RNDIS_DWORD_ALIGNED
	boolean "Use double word aligned"
	depends on USB_G_ANDROID
	help
		Provides dword aligned for DMA controller.

source "drivers/usb/gadget/legacy/Kconfig"

endchoice
+0 −4
Original line number Diff line number Diff line
@@ -9,8 +9,4 @@ obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o
libcomposite-y			:= usbstring.o config.o epautoconf.o
libcomposite-y			+= composite.o functions.o configfs.o u_f.o

g_android-y			:= android.o

obj-$(CONFIG_USB_GADGET)	+= udc/ function/ legacy/

obj-$(CONFIG_USB_G_ANDROID)	+= g_android.o
+86 −0
Original line number Diff line number Diff line
@@ -86,12 +86,15 @@ ffs_setup_state_clear_cancelled(struct ffs_data *ffs)
		cmpxchg(&ffs->setup_state, FFS_SETUP_CANCELLED, FFS_NO_SETUP);
}

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 *,
@@ -1616,6 +1619,71 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count)
	kfree(epfiles);
}

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)
{
@@ -2888,6 +2956,24 @@ 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)
{
+56 −0
Original line number Diff line number Diff line
@@ -870,6 +870,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;
+20 −0
Original line number Diff line number Diff line
@@ -313,6 +313,26 @@ config USB_G_PRINTER
	  For more information, see Documentation/usb/gadget_printer.txt
	  which includes sample code for accessing the device file.

config USB_G_ANDROID
	boolean "Android Composite Gadget"
	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
	  and rndis.
	  Each function can be configured and enabled/disabled
	  dynamically from userspace through a sysfs interface.

config USB_ANDROID_RNDIS_DWORD_ALIGNED
	boolean "Use double word aligned"
	depends on USB_G_ANDROID
	help
		Provides dword aligned for DMA controller.

if TTY

config USB_CDC_COMPOSITE
Loading