[PATCH 21/23] usb: gadget: f_sourcesink: convert to new API

From: Robert Baldyga
Date: Tue Nov 03 2015 - 07:55:25 EST


Generate descriptors in new format and attach them to USB function in
prep_descs(). Change set_alt() implementation and implement clear_alt()
operation. Get rid of get_alt() callback, as now USB_REQ_GET_INTERFACE
is handled automatically by composite framwework. 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.baldyga@xxxxxxxxxxx>
---
drivers/usb/gadget/function/f_sourcesink.c | 314 ++++++-----------------------
drivers/usb/gadget/function/g_zero.h | 3 -
drivers/usb/gadget/legacy/zero.c | 3 +
3 files changed, 65 insertions(+), 255 deletions(-)

diff --git a/drivers/usb/gadget/function/f_sourcesink.c b/drivers/usb/gadget/function/f_sourcesink.c
index d8f5f56..6e3d3df 100644
--- a/drivers/usb/gadget/function/f_sourcesink.c
+++ b/drivers/usb/gadget/function/f_sourcesink.c
@@ -51,7 +51,6 @@ struct f_sourcesink {
struct usb_ep *out_ep;
struct usb_ep *iso_in_ep;
struct usb_ep *iso_out_ep;
- int cur_alt;

struct usb_request *in_req;
struct usb_request *out_req;
@@ -132,19 +131,6 @@ static struct usb_endpoint_descriptor fs_iso_sink_desc = {
.bInterval = 4,
};

-static struct usb_descriptor_header *fs_source_sink_descs[] = {
- (struct usb_descriptor_header *) &source_sink_intf_alt0,
- (struct usb_descriptor_header *) &fs_sink_desc,
- (struct usb_descriptor_header *) &fs_source_desc,
- (struct usb_descriptor_header *) &source_sink_intf_alt1,
-#define FS_ALT_IFC_1_OFFSET 3
- (struct usb_descriptor_header *) &fs_sink_desc,
- (struct usb_descriptor_header *) &fs_source_desc,
- (struct usb_descriptor_header *) &fs_iso_sink_desc,
- (struct usb_descriptor_header *) &fs_iso_source_desc,
- NULL,
-};
-
/* high speed support: */

static struct usb_endpoint_descriptor hs_source_desc = {
@@ -181,19 +167,6 @@ static struct usb_endpoint_descriptor hs_iso_sink_desc = {
.bInterval = 4,
};

-static struct usb_descriptor_header *hs_source_sink_descs[] = {
- (struct usb_descriptor_header *) &source_sink_intf_alt0,
- (struct usb_descriptor_header *) &hs_source_desc,
- (struct usb_descriptor_header *) &hs_sink_desc,
- (struct usb_descriptor_header *) &source_sink_intf_alt1,
-#define HS_ALT_IFC_1_OFFSET 3
- (struct usb_descriptor_header *) &hs_source_desc,
- (struct usb_descriptor_header *) &hs_sink_desc,
- (struct usb_descriptor_header *) &hs_iso_source_desc,
- (struct usb_descriptor_header *) &hs_iso_sink_desc,
- NULL,
-};
-
/* super speed support: */

static struct usb_endpoint_descriptor ss_source_desc = {
@@ -266,24 +239,24 @@ static struct usb_ss_ep_comp_descriptor ss_iso_sink_comp_desc = {
.wBytesPerInterval = cpu_to_le16(1024),
};

-static struct usb_descriptor_header *ss_source_sink_descs[] = {
- (struct usb_descriptor_header *) &source_sink_intf_alt0,
- (struct usb_descriptor_header *) &ss_source_desc,
- (struct usb_descriptor_header *) &ss_source_comp_desc,
- (struct usb_descriptor_header *) &ss_sink_desc,
- (struct usb_descriptor_header *) &ss_sink_comp_desc,
- (struct usb_descriptor_header *) &source_sink_intf_alt1,
-#define SS_ALT_IFC_1_OFFSET 5
- (struct usb_descriptor_header *) &ss_source_desc,
- (struct usb_descriptor_header *) &ss_source_comp_desc,
- (struct usb_descriptor_header *) &ss_sink_desc,
- (struct usb_descriptor_header *) &ss_sink_comp_desc,
- (struct usb_descriptor_header *) &ss_iso_source_desc,
- (struct usb_descriptor_header *) &ss_iso_source_comp_desc,
- (struct usb_descriptor_header *) &ss_iso_sink_desc,
- (struct usb_descriptor_header *) &ss_iso_sink_comp_desc,
- NULL,
-};
+USB_COMPOSITE_ENDPOINT(ep_source, &fs_source_desc, &hs_source_desc,
+ &ss_source_desc, &ss_source_comp_desc);
+USB_COMPOSITE_ENDPOINT(ep_sink, &fs_sink_desc, &hs_sink_desc,
+ &ss_sink_desc, &ss_sink_comp_desc);
+USB_COMPOSITE_ENDPOINT(ep_iso_source, &fs_iso_source_desc, &hs_iso_source_desc,
+ &ss_iso_source_desc, &ss_iso_source_comp_desc);
+USB_COMPOSITE_ENDPOINT(ep_iso_sink, &fs_iso_sink_desc, &hs_iso_sink_desc,
+ &ss_iso_sink_desc, &ss_iso_sink_comp_desc);
+
+USB_COMPOSITE_ALTSETTING(altset0, &source_sink_intf_alt0, &ep_source, &ep_sink);
+USB_COMPOSITE_ALTSETTING(altset1, &source_sink_intf_alt1, &ep_source, &ep_sink,
+ &ep_iso_source, &ep_iso_sink);
+
+USB_COMPOSITE_INTERFACE(intf0, &altset0, &altset1);
+USB_COMPOSITE_INTERFACE(intf0_no_iso, &altset0);
+
+USB_COMPOSITE_DESCRIPTORS(source_sink_descs, &intf0);
+USB_COMPOSITE_DESCRIPTORS(source_sink_descs_no_iso, &intf0_no_iso);

/* function-specific strings: */

@@ -317,65 +290,12 @@ void free_ep_req(struct usb_ep *ep, struct usb_request *req)
usb_ep_free_request(ep, req);
}

-static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
-{
- int value;
-
- value = usb_ep_disable(ep);
- if (value < 0)
- DBG(cdev, "disable %s --> %d\n", ep->name, value);
-}
-
-void disable_endpoints(struct usb_composite_dev *cdev,
- struct usb_ep *in, struct usb_ep *out,
- struct usb_ep *iso_in, struct usb_ep *iso_out)
-{
- disable_ep(cdev, in);
- disable_ep(cdev, out);
- if (iso_in)
- disable_ep(cdev, iso_in);
- if (iso_out)
- disable_ep(cdev, iso_out);
-}
-
-static int
-sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
+static int sourcesink_prep_descs(struct usb_function *f)
{
- struct usb_composite_dev *cdev = c->cdev;
struct f_sourcesink *ss = func_to_ss(f);
- int id;
- int ret;

- /* allocate interface ID(s) */
- id = usb_interface_id(c, f);
- if (id < 0)
- return id;
- source_sink_intf_alt0.bInterfaceNumber = id;
- source_sink_intf_alt1.bInterfaceNumber = id;
-
- /* allocate bulk endpoints */
- ss->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc);
- if (!ss->in_ep)
- goto autoconf_fail;
-
- ss->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_sink_desc);
- if (!ss->out_ep)
- goto autoconf_fail;
-
- /* support high speed hardware */
- hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
- hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
-
- /* support super speed hardware */
- ss_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
- ss_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
-
- if (!ss->isoc_enabled) {
- fs_source_sink_descs[FS_ALT_IFC_1_OFFSET] = NULL;
- hs_source_sink_descs[HS_ALT_IFC_1_OFFSET] = NULL;
- ss_source_sink_descs[SS_ALT_IFC_1_OFFSET] = NULL;
- goto no_iso;
- }
+ if (!ss->isoc_enabled)
+ return usb_function_set_descs(f, &source_sink_descs_no_iso);

/* sanity check the isoc module parameters */
if (ss->isoc_interval < 1)
@@ -395,15 +315,6 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
1023 : ss->isoc_maxpacket;
fs_iso_sink_desc.bInterval = ss->isoc_interval;

- /* allocate iso endpoints */
- ss->iso_in_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_source_desc);
- if (!ss->iso_in_ep)
- goto autoconf_fail;
-
- ss->iso_out_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_sink_desc);
- if (!ss->iso_out_ep)
- goto autoconf_fail;
-
if (ss->isoc_maxpacket > 1024)
ss->isoc_maxpacket = 1024;
/*
@@ -414,14 +325,10 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
hs_iso_source_desc.wMaxPacketSize = ss->isoc_maxpacket;
hs_iso_source_desc.wMaxPacketSize |= ss->isoc_mult << 11;
hs_iso_source_desc.bInterval = ss->isoc_interval;
- hs_iso_source_desc.bEndpointAddress =
- fs_iso_source_desc.bEndpointAddress;

hs_iso_sink_desc.wMaxPacketSize = ss->isoc_maxpacket;
hs_iso_sink_desc.wMaxPacketSize |= ss->isoc_mult << 11;
hs_iso_sink_desc.bInterval = ss->isoc_interval;
- hs_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;
-
/*
* Fill in the SS isoc descriptors from the module parameters.
* We assume that the user knows what they are doing and won't
@@ -433,8 +340,6 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
ss_iso_source_comp_desc.bMaxBurst = ss->isoc_maxburst;
ss_iso_source_comp_desc.wBytesPerInterval = ss->isoc_maxpacket *
(ss->isoc_mult + 1) * (ss->isoc_maxburst + 1);
- ss_iso_source_desc.bEndpointAddress =
- fs_iso_source_desc.bEndpointAddress;

ss_iso_sink_desc.wMaxPacketSize = ss->isoc_maxpacket;
ss_iso_sink_desc.bInterval = ss->isoc_interval;
@@ -442,26 +347,8 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
ss_iso_sink_comp_desc.bMaxBurst = ss->isoc_maxburst;
ss_iso_sink_comp_desc.wBytesPerInterval = ss->isoc_maxpacket *
(ss->isoc_mult + 1) * (ss->isoc_maxburst + 1);
- ss_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;

-no_iso:
- ret = usb_assign_descriptors(f, fs_source_sink_descs,
- hs_source_sink_descs, ss_source_sink_descs);
- if (ret)
- return ret;
-
- DBG(cdev, "%s speed %s: IN/%s, OUT/%s, ISO-IN/%s, ISO-OUT/%s\n",
- (gadget_is_superspeed(c->cdev->gadget) ? "super" :
- (gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")),
- f->name, ss->in_ep->name, ss->out_ep->name,
- ss->iso_in_ep ? ss->iso_in_ep->name : "<none>",
- ss->iso_out_ep ? ss->iso_out_ep->name : "<none>");
- return 0;
-
-autoconf_fail:
- ERROR(cdev, "%s: can't autoconfigure on %s\n",
- f->name, cdev->gadget->name);
- return -ENODEV;
+ return usb_function_set_descs(f, &source_sink_descs);
}

static void
@@ -475,7 +362,6 @@ sourcesink_free_func(struct usb_function *f)
opts->refcnt--;
mutex_unlock(&opts->lock);

- usb_free_all_descriptors(f);
kfree(func_to_ss(f));
}

@@ -658,136 +544,61 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in,
return status;
}

-static void disable_source_sink(struct f_sourcesink *ss)
-{
- struct usb_composite_dev *cdev;
-
- cdev = ss->function.config->cdev;
- disable_endpoints(cdev, ss->in_ep, ss->out_ep, ss->iso_in_ep,
- ss->iso_out_ep);
- VDBG(cdev, "%s disabled\n", ss->function.name);
-}
-
-static int
-enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss,
- int alt)
-{
- int result = 0;
- int speed = cdev->gadget->speed;
- struct usb_ep *ep;
-
- /* one bulk endpoint writes (sources) zeroes IN (to the host) */
- ep = ss->in_ep;
- result = config_ep_by_speed(cdev->gadget, &(ss->function), ep);
- if (result)
- return result;
- result = usb_ep_enable(ep);
- if (result < 0)
- return result;
- ep->driver_data = ss;
-
- result = source_sink_start_ep(ss, true, false, speed);
- if (result < 0) {
-fail:
- ep = ss->in_ep;
- usb_ep_disable(ep);
- return result;
- }
-
- /* one bulk endpoint reads (sinks) anything OUT (from the host) */
- ep = ss->out_ep;
- result = config_ep_by_speed(cdev->gadget, &(ss->function), ep);
- if (result)
- goto fail;
- result = usb_ep_enable(ep);
- if (result < 0)
- goto fail;
- ep->driver_data = ss;
-
- result = source_sink_start_ep(ss, false, false, speed);
- if (result < 0) {
-fail2:
- ep = ss->out_ep;
- usb_ep_disable(ep);
- goto fail;
- }
-
- if (alt == 0)
- goto out;
-
- /* one iso endpoint writes (sources) zeroes IN (to the host) */
- ep = ss->iso_in_ep;
- if (ep) {
- result = config_ep_by_speed(cdev->gadget, &(ss->function), ep);
- if (result)
- goto fail2;
- result = usb_ep_enable(ep);
- if (result < 0)
- goto fail2;
- ep->driver_data = ss;
-
- result = source_sink_start_ep(ss, true, true, speed);
- if (result < 0) {
-fail3:
- ep = ss->iso_in_ep;
- if (ep)
- usb_ep_disable(ep);
- goto fail2;
- }
- }
-
- /* one iso endpoint reads (sinks) anything OUT (from the host) */
- ep = ss->iso_out_ep;
- if (ep) {
- result = config_ep_by_speed(cdev->gadget, &(ss->function), ep);
- if (result)
- goto fail3;
- result = usb_ep_enable(ep);
- if (result < 0)
- goto fail3;
- ep->driver_data = ss;
-
- result = source_sink_start_ep(ss, false, true, speed);
- if (result < 0) {
- usb_ep_disable(ep);
- goto fail3;
- }
- }
-out:
- ss->cur_alt = alt;
-
- DBG(cdev, "%s enabled, alt intf %d\n", ss->function.name, alt);
- return result;
-}
-
static int sourcesink_set_alt(struct usb_function *f,
unsigned intf, unsigned alt)
{
struct f_sourcesink *ss = func_to_ss(f);
struct usb_composite_dev *cdev = f->config->cdev;
+ int speed = cdev->gadget->speed;
+ int ret;

- disable_source_sink(ss);
- return enable_source_sink(cdev, ss, alt);
-}
+ ss->in_ep = usb_function_get_ep(f, intf, 0);
+ if (!ss->in_ep)
+ return -ENODEV;
+ ss->in_ep->driver_data = ss;
+ ret = source_sink_start_ep(ss, true, false, speed);
+ if (ret < 0)
+ return ret;

-static int sourcesink_get_alt(struct usb_function *f, unsigned intf)
-{
- struct f_sourcesink *ss = func_to_ss(f);
+ ss->out_ep = usb_function_get_ep(f, intf, 1);
+ if (!ss->out_ep)
+ return -ENODEV;
+ ss->out_ep->driver_data = ss;
+ ret = source_sink_start_ep(ss, false, false, speed);
+ if (ret < 0)
+ return ret;
+
+ if (alt == 1) {
+ ss->iso_in_ep = usb_function_get_ep(f, intf, 2);
+ if (!ss->iso_in_ep)
+ return -ENODEV;
+ ss->iso_in_ep->driver_data = ss;
+ ret = source_sink_start_ep(ss, true, true, speed);
+ if (ret < 0)
+ return ret;
+
+ ss->iso_out_ep = usb_function_get_ep(f, intf, 3);
+ if (!ss->iso_out_ep)
+ return -ENODEV;
+ ss->iso_out_ep->driver_data = ss;
+ ret = source_sink_start_ep(ss, false, true, speed);
+ if (ret < 0)
+ return ret;
+ }

- return ss->cur_alt;
+ return 0;
}

-static void sourcesink_disable(struct usb_function *f)
+static void sourcesink_clear_alt(struct usb_function *f,
+ unsigned intf, unsigned alt)
{
struct f_sourcesink *ss = func_to_ss(f);
int i;

- disable_source_sink(ss);
-
free_ep_req(ss->in_ep, ss->in_req);
free_ep_req(ss->out_ep, ss->out_req);

- if (ss->iso_in_ep) {
+ if (alt == 1) {
for (i = 0; i < REQ_CNT; i++) {
free_ep_req(ss->iso_in_ep, ss->iso_in_req[i]);
free_ep_req(ss->iso_out_ep, ss->iso_out_req[i]);
@@ -894,10 +705,9 @@ static struct usb_function *source_sink_alloc_func(
ss->buflen = ss_opts->bulk_buflen;

ss->function.name = "source/sink";
- ss->function.bind = sourcesink_bind;
+ ss->function.prep_descs = sourcesink_prep_descs;
ss->function.set_alt = sourcesink_set_alt;
- ss->function.get_alt = sourcesink_get_alt;
- ss->function.disable = sourcesink_disable;
+ ss->function.clear_alt = sourcesink_clear_alt;
ss->function.setup = sourcesink_setup;
ss->function.strings = sourcesink_strings;

diff --git a/drivers/usb/gadget/function/g_zero.h b/drivers/usb/gadget/function/g_zero.h
index 8a99071..34857e9 100644
--- a/drivers/usb/gadget/function/g_zero.h
+++ b/drivers/usb/gadget/function/g_zero.h
@@ -63,8 +63,5 @@ int lb_modinit(void);

/* common utilities */
void free_ep_req(struct usb_ep *ep, struct usb_request *req);
-void disable_endpoints(struct usb_composite_dev *cdev,
- struct usb_ep *in, struct usb_ep *out,
- struct usb_ep *iso_in, struct usb_ep *iso_out);

#endif /* __G_ZERO_H */
diff --git a/drivers/usb/gadget/legacy/zero.c b/drivers/usb/gadget/legacy/zero.c
index 097bdaf..76fc97d 100644
--- a/drivers/usb/gadget/legacy/zero.c
+++ b/drivers/usb/gadget/legacy/zero.c
@@ -361,6 +361,9 @@ static int zero_bind(struct usb_composite_dev *cdev)
status = usb_add_function(&sourcesink_driver, func_ss);
if (status)
goto err_free_otg_desc;
+ status = usb_config_do_bind(&sourcesink_driver);
+ if (status)
+ goto err_free_otg_desc;

usb_ep_autoconfig_reset(cdev->gadget);
status = usb_add_function(&loopback_driver, func_lb);
--
1.9.1

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