[PATCH 01/10] usb/gadget: provide a wrapper around SourceSink's setup function

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The setup request can be sent to an interface/endpoint or to the device
itself. If it is sent to an interface then we forward it to the function
that is mapped to that interface. The same is true if an endpoint is the
target of the setup request.
If the device is the target of a setup request then we forward it to the
->setup() callback of the currently active configuration.
In case of the sourcesink function the requests are function specific
but are sent to the device.
This patch introduces a setup wraper at configuration level which
forwards the requests to the function. This allows to keep the function
specific code within the function and we need just a hint at config
level to forward the request.
The here introduces global variable will be moved into the gadget (which
combines the two functions) in a later patch.
The alternative would to attempt to deliver the request to each function
as long as they return ENOTSUPP. SourceSink is currently the only gadget
using ->setup() at config level.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx>
---
 drivers/usb/gadget/f_sourcesink.c |   70 ++++++++++++++++++++++++-------------
 1 file changed, 45 insertions(+), 25 deletions(-)

diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c
index 6ef3ea2..e5c0504 100644
--- a/drivers/usb/gadget/f_sourcesink.c
+++ b/drivers/usb/gadget/f_sourcesink.c
@@ -449,11 +449,14 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
 	return 0;
 }
 
+static struct usb_function *global_ss_func;
+
 static void
 sourcesink_unbind(struct usb_configuration *c, struct usb_function *f)
 {
 	usb_free_all_descriptors(f);
 	kfree(func_to_ss(f));
+	global_ss_func = NULL;
 }
 
 /* optionally require specific source/sink data patterns  */
@@ -757,32 +760,10 @@ static void sourcesink_disable(struct usb_function *f)
 }
 
 /*-------------------------------------------------------------------------*/
-
-static int __init sourcesink_bind_config(struct usb_configuration *c)
-{
-	struct f_sourcesink	*ss;
-	int			status;
-
-	ss = kzalloc(sizeof *ss, GFP_KERNEL);
-	if (!ss)
-		return -ENOMEM;
-
-	ss->function.name = "source/sink";
-	ss->function.bind = sourcesink_bind;
-	ss->function.unbind = sourcesink_unbind;
-	ss->function.set_alt = sourcesink_set_alt;
-	ss->function.get_alt = sourcesink_get_alt;
-	ss->function.disable = sourcesink_disable;
-
-	status = usb_add_function(c, &ss->function);
-	if (status)
-		kfree(ss);
-	return status;
-}
-
-static int sourcesink_setup(struct usb_configuration *c,
+static int sourcesink_setup(struct usb_function *f,
 		const struct usb_ctrlrequest *ctrl)
 {
+	struct usb_configuration        *c = f->config;
 	struct usb_request	*req = c->cdev->req;
 	int			value = -EOPNOTSUPP;
 	u16			w_index = le16_to_cpu(ctrl->wIndex);
@@ -851,10 +832,49 @@ static int sourcesink_setup(struct usb_configuration *c,
 	return value;
 }
 
+static int __init sourcesink_bind_config(struct usb_configuration *c)
+{
+	struct f_sourcesink	*ss;
+	int			status;
+
+	ss = kzalloc(sizeof(*ss), GFP_KERNEL);
+	if (!ss)
+		return -ENOMEM;
+
+	global_ss_func = &ss->function;
+
+	ss->function.name = "source/sink";
+	ss->function.bind = sourcesink_bind;
+	ss->function.unbind = sourcesink_unbind;
+	ss->function.set_alt = sourcesink_set_alt;
+	ss->function.get_alt = sourcesink_get_alt;
+	ss->function.disable = sourcesink_disable;
+	ss->function.setup = sourcesink_setup;
+
+	status = usb_add_function(c, &ss->function);
+	if (status)
+		kfree(ss);
+	return status;
+}
+
+static int ss_config_setup(struct usb_configuration *c,
+		const struct usb_ctrlrequest *ctrl)
+{
+	if (!global_ss_func)
+		return -EOPNOTSUPP;
+	switch (ctrl->bRequest) {
+		case 0x5b:
+		case 0x5c:
+			return global_ss_func->setup(global_ss_func, ctrl);
+		default:
+			return -EOPNOTSUPP;
+	}
+}
+
 static struct usb_configuration sourcesink_driver = {
 	.label			= "source/sink",
 	.strings		= sourcesink_strings,
-	.setup			= sourcesink_setup,
+	.setup			= ss_config_setup,
 	.bConfigurationValue	= 3,
 	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
 	/* .iConfiguration	= DYNAMIC */
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux