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

Commit 21214278 authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman
Browse files

usb gadget: defer obex enumeration



Some USB peripheral controller drivers support software control
over the data pullup.  Use those controls to prevent the OBEX
function from enumerating until the userspace server has opened
the /dev/ttyGS* node it will use to implement protocol chitchat
with the USB host.

Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 3086775a
Loading
Loading
Loading
Loading
+54 −7
Original line number Original line Diff line number Diff line
@@ -35,13 +35,8 @@
 * This CDC OBEX function support just packages a TTY-ish byte stream.
 * This CDC OBEX function support just packages a TTY-ish byte stream.
 * A user mode server will put it into "raw" mode and handle all the
 * A user mode server will put it into "raw" mode and handle all the
 * relevant protocol details ... this is just a kernel passthrough.
 * relevant protocol details ... this is just a kernel passthrough.
 *
 * When possible, we prevent gadget enumeration until that server is
 * REVISIT this driver shouldn't actually activate before that user mode
 * ready to handle the commands.
 * server is ready to respond!  When the "serial gadget" utility code
 * adds open/close notifications, this driver should use them with new
 * (TBS) composite gadget hooks that wrap usb_gadget_disconnect() and
 * usb_gadget_connect() calls with refcounts ... disconnect() when we
 * bind, then connect() when the user server code is ready to respond.
 */
 */


struct obex_ep_descs {
struct obex_ep_descs {
@@ -54,6 +49,7 @@ struct f_obex {
	u8				ctrl_id;
	u8				ctrl_id;
	u8				data_id;
	u8				data_id;
	u8				port_num;
	u8				port_num;
	u8				can_activate;


	struct obex_ep_descs		fs;
	struct obex_ep_descs		fs;
	struct obex_ep_descs		hs;
	struct obex_ep_descs		hs;
@@ -64,6 +60,11 @@ static inline struct f_obex *func_to_obex(struct usb_function *f)
	return container_of(f, struct f_obex, port.func);
	return container_of(f, struct f_obex, port.func);
}
}


static inline struct f_obex *port_to_obex(struct gserial *p)
{
	return container_of(p, struct f_obex, port);
}

/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/


#define OBEX_CTRL_IDX	0
#define OBEX_CTRL_IDX	0
@@ -269,6 +270,38 @@ static void obex_disable(struct usb_function *f)


/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/


static void obex_connect(struct gserial *g)
{
	struct f_obex		*obex = port_to_obex(g);
	struct usb_composite_dev *cdev = g->func.config->cdev;
	int			status;

	if (!obex->can_activate)
		return;

	status = usb_function_activate(&g->func);
	if (status)
		DBG(cdev, "obex ttyGS%d function activate --> %d\n",
			obex->port_num, status);
}

static void obex_disconnect(struct gserial *g)
{
	struct f_obex		*obex = port_to_obex(g);
	struct usb_composite_dev *cdev = g->func.config->cdev;
	int			status;

	if (!obex->can_activate)
		return;

	status = usb_function_deactivate(&g->func);
	if (status)
		DBG(cdev, "obex ttyGS%d function deactivate --> %d\n",
			obex->port_num, status);
}

/*-------------------------------------------------------------------------*/

static int __init
static int __init
obex_bind(struct usb_configuration *c, struct usb_function *f)
obex_bind(struct usb_configuration *c, struct usb_function *f)
{
{
@@ -338,6 +371,17 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
				f->descriptors, &obex_hs_ep_out_desc);
				f->descriptors, &obex_hs_ep_out_desc);
	}
	}


	/* Avoid letting this gadget enumerate until the userspace
	 * OBEX server is active.
	 */
	status = usb_function_deactivate(f);
	if (status < 0)
		WARNING(cdev, "obex ttyGS%d: can't prevent enumeration, %d\n",
			obex->port_num, status);
	else
		obex->can_activate = true;


	DBG(cdev, "obex ttyGS%d: %s speed IN/%s OUT/%s\n",
	DBG(cdev, "obex ttyGS%d: %s speed IN/%s OUT/%s\n",
			obex->port_num,
			obex->port_num,
			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
@@ -426,6 +470,9 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)


	obex->port_num = port_num;
	obex->port_num = port_num;


	obex->port.connect = obex_connect;
	obex->port.disconnect = obex_disconnect;

	obex->port.func.name = "obex";
	obex->port.func.name = "obex";
	obex->port.func.strings = obex_strings;
	obex->port.func.strings = obex_strings;
	/* descriptors are per-instance copies */
	/* descriptors are per-instance copies */