]> git.karo-electronics.de Git - linux-beck.git/commitdiff
usb: gadget: provide a wrapper around SourceSink's setup function
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>
Sun, 23 Dec 2012 20:09:57 +0000 (21:09 +0100)
committerFelipe Balbi <balbi@ti.com>
Mon, 21 Jan 2013 18:52:38 +0000 (20:52 +0200)
The setup request can be sent to an interface/endpoint or to the device
itself. If it is sent to an interface / endpoint then we forward it to
the function that is mapped to that interface / endpoint.
If the device is the target of the 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 wrapper at configuration level which
forwards the request to the function. By using this wrapper we can keep
the function specific code within the function file and we need just a
hint at config level to forward the request.
The here introduced global variable will be moved into the gadget (which
combines the two functions) in a later patch.
SourceSink is currently the only function using ->setup() at config level.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/gadget/f_sourcesink.c

index de608864c6db781ac3539280212cad9c7af5fc00..bac04b0c628eb40d642b9097c55e82666c97a231 100644 (file)
@@ -449,11 +449,14 @@ no_iso:
        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  */
@@ -756,32 +759,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);
@@ -850,10 +831,49 @@ unknown:
        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 */