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

Commit ff47f594 authored by Sebastian Andrzej Siewior's avatar Sebastian Andrzej Siewior Committed by Felipe Balbi
Browse files

usb: gadget: f_acm: convert to new function interface with backwards compatibility



This patch converts f_acm into a module which uses the new function
interface. It also converts one of its users that is g_serial to make
use of it. The other users of it (g_nokia for instance) are still using
the old include file system and should not notice the change at all. So
they can be converter later independently.

Signed-off-by: default avatarSebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 19b10a88
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -500,6 +500,9 @@ config USB_LIBCOMPOSITE
	tristate
	depends on USB_GADGET

config USB_F_ACM
	tristate

config USB_F_SS_LB
	tristate

@@ -758,6 +761,7 @@ config USB_GADGET_TARGET
config USB_G_SERIAL
	tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
	select USB_U_SERIAL
	select USB_F_ACM
	select USB_LIBCOMPOSITE
	help
	  The Serial Gadget talks to the Linux-USB generic serial driver.
+1 −0
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ obj-$(CONFIG_USB_G_ACM_MS) += g_acm_ms.o
obj-$(CONFIG_USB_GADGET_TARGET)	+= tcm_usb_gadget.o

# USB Functions
obj-$(CONFIG_USB_F_ACM)		+= f_acm.o
f_ss_lb-y			:= f_loopback.o f_sourcesink.o
obj-$(CONFIG_USB_F_SS_LB)	+= f_ss_lb.o
obj-$(CONFIG_USB_U_SERIAL)	+= u_serial.o
+1 −1
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@
 * the runtime footprint, and giving us at least some parts of what
 * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
 */

#define USB_FACM_INCLUDED
#include "f_acm.c"
#include "f_mass_storage.c"

+1 −1
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ USB_GADGET_COMPOSITE_OPTIONS();
 * the runtime footprint, and giving us at least some parts of what
 * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
 */

#define USB_FACM_INCLUDED
#include "f_acm.c"
#include "f_ecm.c"
#include "u_ether.c"
+107 −34
Original line number Diff line number Diff line
@@ -16,7 +16,9 @@

#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/err.h>

#include "u_serial.h"
#include "gadget_chips.h"
@@ -608,6 +610,22 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
	int			status;
	struct usb_ep		*ep;

	/* REVISIT might want instance-specific strings to help
	 * distinguish instances ...
	 */

	/* maybe allocate device-global string IDs, and patch descriptors */
	if (acm_string_defs[0].id == 0) {
		status = usb_string_ids_tab(c->cdev, acm_string_defs);
		if (status < 0)
			return status;
		acm_control_interface_desc.iInterface =
			acm_string_defs[ACM_CTRL_IDX].id;
		acm_data_interface_desc.iInterface =
			acm_string_defs[ACM_DATA_IDX].id;
		acm_iad_descriptor.iFunction = acm_string_defs[ACM_IAD_IDX].id;
	}

	/* allocate instance-specific interface IDs, and patch descriptors */
	status = usb_interface_id(c, f);
	if (status < 0)
@@ -700,13 +718,40 @@ fail:
	return status;
}

static struct f_acm *acm_alloc_basic_func(void)
{
	struct f_acm	*acm;

	acm = kzalloc(sizeof(*acm), GFP_KERNEL);
	if (!acm)
		return NULL;

	spin_lock_init(&acm->lock);

	acm->port.connect = acm_connect;
	acm->port.disconnect = acm_disconnect;
	acm->port.send_break = acm_send_break;

	acm->port.func.name = "acm";
	acm->port.func.strings = acm_strings;
	/* descriptors are per-instance copies */
	acm->port.func.bind = acm_bind;
	acm->port.func.set_alt = acm_set_alt;
	acm->port.func.setup = acm_setup;
	acm->port.func.disable = acm_disable;

	return acm;
}

#ifdef USB_FACM_INCLUDED
static void
acm_unbind(struct usb_configuration *c, struct usb_function *f)
acm_old_unbind(struct usb_configuration *c, struct usb_function *f)
{
	struct f_acm		*acm = func_to_acm(f);

	acm_string_defs[0].id = 0;
	usb_free_all_descriptors(f);
	if (acm->notify_req)
		gs_free_req(acm->notify, acm->notify_req);
	kfree(acm);
}
@@ -725,46 +770,74 @@ int acm_bind_config(struct usb_configuration *c, u8 port_num)
	struct f_acm	*acm;
	int		status;

	/* REVISIT might want instance-specific strings to help
	 * distinguish instances ...
	 */

	/* maybe allocate device-global string IDs, and patch descriptors */
	if (acm_string_defs[0].id == 0) {
		status = usb_string_ids_tab(c->cdev, acm_string_defs);
		if (status < 0)
			return status;
		acm_control_interface_desc.iInterface =
			acm_string_defs[ACM_CTRL_IDX].id;
		acm_data_interface_desc.iInterface =
			acm_string_defs[ACM_DATA_IDX].id;
		acm_iad_descriptor.iFunction = acm_string_defs[ACM_IAD_IDX].id;
	}

	/* allocate and initialize one new instance */
	acm = kzalloc(sizeof *acm, GFP_KERNEL);
	acm = acm_alloc_basic_func();
	if (!acm)
		return -ENOMEM;

	spin_lock_init(&acm->lock);

	acm->port_num = port_num;

	acm->port.connect = acm_connect;
	acm->port.disconnect = acm_disconnect;
	acm->port.send_break = acm_send_break;

	acm->port.func.name = "acm";
	acm->port.func.strings = acm_strings;
	/* descriptors are per-instance copies */
	acm->port.func.bind = acm_bind;
	acm->port.func.unbind = acm_unbind;
	acm->port.func.set_alt = acm_set_alt;
	acm->port.func.setup = acm_setup;
	acm->port.func.disable = acm_disable;
	acm->port.func.unbind = acm_old_unbind;

	status = usb_add_function(c, &acm->port.func);
	if (status)
		kfree(acm);
	return status;
}

#else

static void acm_unbind(struct usb_configuration *c, struct usb_function *f)
{
	struct f_acm		*acm = func_to_acm(f);

	acm_string_defs[0].id = 0;
	usb_free_all_descriptors(f);
	if (acm->notify_req)
		gs_free_req(acm->notify, acm->notify_req);
}

static void acm_free_func(struct usb_function *f)
{
	struct f_acm		*acm = func_to_acm(f);

	kfree(acm);
}

static struct usb_function *acm_alloc_func(struct usb_function_instance *fi)
{
	struct f_serial_opts *opts;
	struct f_acm *acm;

	acm = acm_alloc_basic_func();
	if (!acm)
		return ERR_PTR(-ENOMEM);

	opts = container_of(fi, struct f_serial_opts, func_inst);
	acm->port_num = opts->port_num;
	acm->port.func.unbind = acm_unbind;
	acm->port.func.free_func = acm_free_func;

	return &acm->port.func;
}

static void acm_free_instance(struct usb_function_instance *fi)
{
	struct f_serial_opts *opts;

	opts = container_of(fi, struct f_serial_opts, func_inst);
	kfree(opts);
}

static struct usb_function_instance *acm_alloc_instance(void)
{
	struct f_serial_opts *opts;

	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
	if (!opts)
		return ERR_PTR(-ENOMEM);
	opts->func_inst.free_func_inst = acm_free_instance;
	return &opts->func_inst;
}
DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func);
MODULE_LICENSE("GPL");
#endif
Loading