Generate descriptors in new format and attach them to USB function in
prep_descs(). Change set_alt() implementation and implement clear_alt()
operation. Remove unnecessary boilerplate code.

Call usb_config_do_bind() in legacy gadget zero, because it uses
usb_add_config_only() instead of usb_add_config() and prepares
configuration manually.

Signed-off-by: Robert Baldyga <r.bald...@samsung.com>
---
 drivers/usb/gadget/function/f_loopback.c | 162 ++++++-------------------------
 drivers/usb/gadget/legacy/zero.c         |   3 +
 2 files changed, 33 insertions(+), 132 deletions(-)

diff --git a/drivers/usb/gadget/function/f_loopback.c 
b/drivers/usb/gadget/function/f_loopback.c
index 7d1fa10..14ba8a9 100644
--- a/drivers/usb/gadget/function/f_loopback.c
+++ b/drivers/usb/gadget/function/f_loopback.c
@@ -76,13 +76,6 @@ static struct usb_endpoint_descriptor fs_loop_sink_desc = {
        .bmAttributes =         USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_descriptor_header *fs_loopback_descs[] = {
-       (struct usb_descriptor_header *) &loopback_intf,
-       (struct usb_descriptor_header *) &fs_loop_sink_desc,
-       (struct usb_descriptor_header *) &fs_loop_source_desc,
-       NULL,
-};
-
 /* high speed support: */
 
 static struct usb_endpoint_descriptor hs_loop_source_desc = {
@@ -101,13 +94,6 @@ static struct usb_endpoint_descriptor hs_loop_sink_desc = {
        .wMaxPacketSize =       cpu_to_le16(512),
 };
 
-static struct usb_descriptor_header *hs_loopback_descs[] = {
-       (struct usb_descriptor_header *) &loopback_intf,
-       (struct usb_descriptor_header *) &hs_loop_source_desc,
-       (struct usb_descriptor_header *) &hs_loop_sink_desc,
-       NULL,
-};
-
 /* super speed support: */
 
 static struct usb_endpoint_descriptor ss_loop_source_desc = {
@@ -142,14 +128,17 @@ static struct usb_ss_ep_comp_descriptor 
ss_loop_sink_comp_desc = {
        .wBytesPerInterval =    0,
 };
 
-static struct usb_descriptor_header *ss_loopback_descs[] = {
-       (struct usb_descriptor_header *) &loopback_intf,
-       (struct usb_descriptor_header *) &ss_loop_source_desc,
-       (struct usb_descriptor_header *) &ss_loop_source_comp_desc,
-       (struct usb_descriptor_header *) &ss_loop_sink_desc,
-       (struct usb_descriptor_header *) &ss_loop_sink_comp_desc,
-       NULL,
-};
+USB_COMPOSITE_ENDPOINT(ep_source, &fs_loop_source_desc, &hs_loop_source_desc,
+               &ss_loop_source_desc, &ss_loop_source_comp_desc);
+USB_COMPOSITE_ENDPOINT(ep_sink, &fs_loop_sink_desc, &hs_loop_sink_desc,
+               &ss_loop_sink_desc, &ss_loop_sink_comp_desc);
+
+USB_COMPOSITE_ALTSETTING(altset0, &loopback_intf, &ep_source, &ep_sink);
+
+USB_COMPOSITE_INTERFACE(intf0, &altset0);
+
+USB_COMPOSITE_DESCRIPTORS(loopback_descs, &intf0);
+
 
 /* function-specific strings: */
 
@@ -170,18 +159,10 @@ static struct usb_gadget_strings *loopback_strings[] = {
 
 /*-------------------------------------------------------------------------*/
 
-static int loopback_bind(struct usb_configuration *c, struct usb_function *f)
+static int loopback_prep_descs(struct usb_function *f)
 {
-       struct usb_composite_dev *cdev = c->cdev;
-       struct f_loopback       *loop = func_to_loop(f);
-       int                     id;
-       int ret;
-
-       /* allocate interface ID(s) */
-       id = usb_interface_id(c, f);
-       if (id < 0)
-               return id;
-       loopback_intf.bInterfaceNumber = id;
+       struct usb_composite_dev *cdev = f->config->cdev;
+       int id;
 
        id = usb_string_id(cdev);
        if (id < 0)
@@ -189,40 +170,7 @@ static int loopback_bind(struct usb_configuration *c, 
struct usb_function *f)
        strings_loopback[0].id = id;
        loopback_intf.iInterface = id;
 
-       /* allocate endpoints */
-
-       loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_source_desc);
-       if (!loop->in_ep) {
-autoconf_fail:
-               ERROR(cdev, "%s: can't autoconfigure on %s\n",
-                       f->name, cdev->gadget->name);
-               return -ENODEV;
-       }
-
-       loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_sink_desc);
-       if (!loop->out_ep)
-               goto autoconf_fail;
-
-       /* support high speed hardware */
-       hs_loop_source_desc.bEndpointAddress =
-               fs_loop_source_desc.bEndpointAddress;
-       hs_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress;
-
-       /* support super speed hardware */
-       ss_loop_source_desc.bEndpointAddress =
-               fs_loop_source_desc.bEndpointAddress;
-       ss_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress;
-
-       ret = usb_assign_descriptors(f, fs_loopback_descs, hs_loopback_descs,
-                       ss_loopback_descs);
-       if (ret)
-               return ret;
-
-       DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
-           (gadget_is_superspeed(c->cdev->gadget) ? "super" :
-            (gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")),
-                       f->name, loop->in_ep->name, loop->out_ep->name);
-       return 0;
+       return usb_function_set_descs(f, &loopback_descs);
 }
 
 static void lb_free_func(struct usb_function *f)
@@ -235,7 +183,6 @@ static void lb_free_func(struct usb_function *f)
        opts->refcnt--;
        mutex_unlock(&opts->lock);
 
-       usb_free_all_descriptors(f);
        kfree(func_to_loop(f));
 }
 
@@ -285,15 +232,6 @@ static void loopback_complete(struct usb_ep *ep, struct 
usb_request *req)
        }
 }
 
-static void disable_loopback(struct f_loopback *loop)
-{
-       struct usb_composite_dev        *cdev;
-
-       cdev = loop->function.config->cdev;
-       disable_endpoints(cdev, loop->in_ep, loop->out_ep, NULL, NULL);
-       VDBG(cdev, "%s disabled\n", loop->function.name);
-}
-
 static inline struct usb_request *lb_alloc_ep_req(struct usb_ep *ep, int len)
 {
        struct f_loopback       *loop = ep->driver_data;
@@ -348,70 +286,30 @@ fail:
        return result;
 }
 
-static int enable_endpoint(struct usb_composite_dev *cdev,
-                          struct f_loopback *loop, struct usb_ep *ep)
-{
-       int                                     result;
-
-       result = config_ep_by_speed(cdev->gadget, &(loop->function), ep);
-       if (result)
-               goto out;
-
-       result = usb_ep_enable(ep);
-       if (result < 0)
-               goto out;
-       ep->driver_data = loop;
-       result = 0;
-
-out:
-       return result;
-}
-
-static int
-enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
-{
-       int                                     result = 0;
-
-       result = enable_endpoint(cdev, loop, loop->in_ep);
-       if (result)
-               goto out;
-
-       result = enable_endpoint(cdev, loop, loop->out_ep);
-       if (result)
-               goto disable_in;
-
-       result = alloc_requests(cdev, loop);
-       if (result)
-               goto disable_out;
-
-       DBG(cdev, "%s enabled\n", loop->function.name);
-       return 0;
-
-disable_out:
-       usb_ep_disable(loop->out_ep);
-disable_in:
-       usb_ep_disable(loop->in_ep);
-out:
-       return result;
-}
-
 static int loopback_set_alt(struct usb_function *f,
                unsigned intf, unsigned alt)
 {
        struct f_loopback       *loop = func_to_loop(f);
        struct usb_composite_dev *cdev = f->config->cdev;
 
-       /* we know alt is zero */
-       disable_loopback(loop);
-       return enable_loopback(cdev, loop);
+       loop->in_ep = usb_function_get_ep(f, intf, 0);
+       if (!loop->in_ep)
+               return -ENODEV;
+       loop->in_ep->driver_data = loop;
+
+       loop->out_ep = usb_function_get_ep(f, intf, 1);
+       if (!loop->out_ep)
+               return -ENODEV;
+       loop->out_ep->driver_data = loop;
+
+       return alloc_requests(cdev, loop);
 }
 
-static void loopback_disable(struct usb_function *f)
+static void loopback_clear_alt(struct usb_function *f,
+               unsigned intf, unsigned alt)
 {
        struct f_loopback       *loop = func_to_loop(f);
 
-       disable_loopback(loop);
-
        free_ep_req(loop->out_ep, loop->out_req);
        usb_ep_free_request(loop->in_ep, loop->in_req);
 }
@@ -437,9 +335,9 @@ static struct usb_function *loopback_alloc(struct 
usb_function_instance *fi)
                loop->qlen = 32;
 
        loop->function.name = "loopback";
-       loop->function.bind = loopback_bind;
+       loop->function.prep_descs = loopback_prep_descs;
        loop->function.set_alt = loopback_set_alt;
-       loop->function.disable = loopback_disable;
+       loop->function.clear_alt = loopback_clear_alt;
        loop->function.strings = loopback_strings;
 
        loop->function.free_func = lb_free_func;
diff --git a/drivers/usb/gadget/legacy/zero.c b/drivers/usb/gadget/legacy/zero.c
index 6adfc88..781ca94 100644
--- a/drivers/usb/gadget/legacy/zero.c
+++ b/drivers/usb/gadget/legacy/zero.c
@@ -378,6 +378,9 @@ static int zero_bind(struct usb_composite_dev *cdev)
        status = usb_add_function(&loopback_driver, func_lb);
        if (status)
                goto err_free_otg_desc;
+       status = usb_config_do_bind(&loopback_driver);
+       if (status)
+               goto err_free_otg_desc;
 
        usb_ep_autoconfig_reset(cdev->gadget);
        usb_composite_overwrite_options(cdev, &coverwrite);
-- 
1.9.1

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

Reply via email to