summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorChris Dickens <christopher.a.dickens@gmail.com>2017-12-31 18:59:43 -0800
committerFelipe Balbi <felipe.balbi@linux.intel.com>2018-03-08 15:12:01 +0200
commit636ba13aec8a0198d3fa4e2246e291a19694b50f (patch)
treee1afdf90a059f69d77a1945cb99e1e2e02e805bb /drivers/usb
parent5d6ae4f0da8a64a185074dabb1b2f8c148efa741 (diff)
usb: gadget: composite: remove duplicated code in OS desc handling
When the host wants to fetch OS descriptors, it sends two requests. The first is only for the header and the second for the full amount specified by the header in the first request. The OS descriptor handling code is distinguishing the header-only requests based on the wLength of the setup packet, but the same code is executed in both cases to construct the actual header. Simplify this by always constructing the header and then filling out the rest of the request if the wLength is greater than the size of the header. Also remove the duplicate code for queueing the request to ep0 by adding a goto label. Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/composite.c72
1 files changed, 22 insertions, 50 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index b8b629c615d3..1924e20f6e8c 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1427,6 +1427,7 @@ static int fill_ext_compat(struct usb_configuration *c, u8 *buf)
int i, count;
count = 16;
+ buf += 16;
for (i = 0; i < c->next_interface_id; ++i) {
struct usb_function *f;
int j;
@@ -1502,6 +1503,7 @@ static int fill_ext_prop(struct usb_configuration *c, int interface, u8 *buf)
f = c->interface[interface];
count = 10; /* header length */
+ buf += 10;
for (j = 0; j < f->os_desc_n; ++j) {
if (interface != f->os_desc_table[j].if_id)
continue;
@@ -1833,22 +1835,14 @@ unknown:
if (w_index != 0x4 || (w_value >> 8))
break;
buf[6] = w_index;
- if (w_length == 0x10) {
- /* Number of ext compat interfaces */
- count = count_ext_compat(os_desc_cfg);
- buf[8] = count;
- count *= 24; /* 24 B/ext compat desc */
- count += 16; /* header */
- put_unaligned_le32(count, buf);
- value = w_length;
- } else {
- /* "extended compatibility ID"s */
- count = count_ext_compat(os_desc_cfg);
- buf[8] = count;
- count *= 24; /* 24 B/ext compat desc */
- count += 16; /* header */
- put_unaligned_le32(count, buf);
- buf += 16;
+ /* Number of ext compat interfaces */
+ count = count_ext_compat(os_desc_cfg);
+ buf[8] = count;
+ count *= 24; /* 24 B/ext compat desc */
+ count += 16; /* header */
+ put_unaligned_le32(count, buf);
+ value = w_length;
+ if (w_length > 0x10) {
value = fill_ext_compat(os_desc_cfg, buf);
value = min_t(u16, w_length, value);
}
@@ -1858,46 +1852,23 @@ unknown:
break;
interface = w_value & 0xFF;
buf[6] = w_index;
- if (w_length == 0x0A) {
- count = count_ext_prop(os_desc_cfg,
- interface);
- put_unaligned_le16(count, buf + 8);
- count = len_ext_prop(os_desc_cfg,
- interface);
- put_unaligned_le32(count, buf);
-
- value = w_length;
- } else {
- count = count_ext_prop(os_desc_cfg,
- interface);
- put_unaligned_le16(count, buf + 8);
- count = len_ext_prop(os_desc_cfg,
- interface);
- put_unaligned_le32(count, buf);
- buf += 10;
+ count = count_ext_prop(os_desc_cfg,
+ interface);
+ put_unaligned_le16(count, buf + 8);
+ count = len_ext_prop(os_desc_cfg,
+ interface);
+ put_unaligned_le32(count, buf);
+ value = w_length;
+ if (w_length > 0x0A) {
value = fill_ext_prop(os_desc_cfg,
interface, buf);
- if (value < 0)
- return value;
- value = min_t(u16, w_length, value);
+ if (value >= 0)
+ value = min_t(u16, w_length, value);
}
break;
}
- if (value >= 0) {
- req->length = value;
- req->context = cdev;
- req->zero = value < w_length;
- value = composite_ep0_queue(cdev, req,
- GFP_ATOMIC);
- if (value < 0) {
- DBG(cdev, "ep_queue --> %d\n", value);
- req->status = 0;
- composite_setup_complete(gadget->ep0,
- req);
- }
- }
- return value;
+ goto check_value;
}
VDBG(cdev,
@@ -1971,6 +1942,7 @@ try_fun_setup:
goto done;
}
+check_value:
/* respond with data transfer before status phase? */
if (value >= 0 && value != USB_GADGET_DELAYED_STATUS) {
req->length = value;