|
@@ -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;
|