|
@@ -1422,7 +1422,7 @@ static int count_ext_compat(struct usb_configuration *c)
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
-static void fill_ext_compat(struct usb_configuration *c, u8 *buf)
|
|
|
+static int fill_ext_compat(struct usb_configuration *c, u8 *buf)
|
|
|
{
|
|
|
int i, count;
|
|
|
|
|
@@ -1449,10 +1449,12 @@ static void fill_ext_compat(struct usb_configuration *c, u8 *buf)
|
|
|
buf += 23;
|
|
|
}
|
|
|
count += 24;
|
|
|
- if (count >= 4096)
|
|
|
- return;
|
|
|
+ if (count + 24 >= USB_COMP_EP0_OS_DESC_BUFSIZ)
|
|
|
+ return count;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ return count;
|
|
|
}
|
|
|
|
|
|
static int count_ext_prop(struct usb_configuration *c, int interface)
|
|
@@ -1497,25 +1499,20 @@ static int fill_ext_prop(struct usb_configuration *c, int interface, u8 *buf)
|
|
|
struct usb_os_desc *d;
|
|
|
struct usb_os_desc_ext_prop *ext_prop;
|
|
|
int j, count, n, ret;
|
|
|
- u8 *start = buf;
|
|
|
|
|
|
f = c->interface[interface];
|
|
|
+ count = 10; /* header length */
|
|
|
for (j = 0; j < f->os_desc_n; ++j) {
|
|
|
if (interface != f->os_desc_table[j].if_id)
|
|
|
continue;
|
|
|
d = f->os_desc_table[j].os_desc;
|
|
|
if (d)
|
|
|
list_for_each_entry(ext_prop, &d->ext_prop, entry) {
|
|
|
- /* 4kB minus header length */
|
|
|
- n = buf - start;
|
|
|
- if (n >= 4086)
|
|
|
- return 0;
|
|
|
-
|
|
|
- count = ext_prop->data_len +
|
|
|
+ n = ext_prop->data_len +
|
|
|
ext_prop->name_len + 14;
|
|
|
- if (count > 4086 - n)
|
|
|
- return -EINVAL;
|
|
|
- usb_ext_prop_put_size(buf, count);
|
|
|
+ if (count + n >= USB_COMP_EP0_OS_DESC_BUFSIZ)
|
|
|
+ return count;
|
|
|
+ usb_ext_prop_put_size(buf, n);
|
|
|
usb_ext_prop_put_type(buf, ext_prop->type);
|
|
|
ret = usb_ext_prop_put_name(buf, ext_prop->name,
|
|
|
ext_prop->name_len);
|
|
@@ -1541,11 +1538,12 @@ static int fill_ext_prop(struct usb_configuration *c, int interface, u8 *buf)
|
|
|
default:
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
- buf += count;
|
|
|
+ buf += n;
|
|
|
+ count += n;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return 0;
|
|
|
+ return count;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -1827,6 +1825,7 @@ unknown:
|
|
|
req->complete = composite_setup_complete;
|
|
|
buf = req->buf;
|
|
|
os_desc_cfg = cdev->os_desc_config;
|
|
|
+ w_length = min_t(u16, w_length, USB_COMP_EP0_OS_DESC_BUFSIZ);
|
|
|
memset(buf, 0, w_length);
|
|
|
buf[5] = 0x01;
|
|
|
switch (ctrl->bRequestType & USB_RECIP_MASK) {
|
|
@@ -1850,8 +1849,8 @@ unknown:
|
|
|
count += 16; /* header */
|
|
|
put_unaligned_le32(count, buf);
|
|
|
buf += 16;
|
|
|
- fill_ext_compat(os_desc_cfg, buf);
|
|
|
- value = w_length;
|
|
|
+ value = fill_ext_compat(os_desc_cfg, buf);
|
|
|
+ value = min_t(u16, w_length, value);
|
|
|
}
|
|
|
break;
|
|
|
case USB_RECIP_INTERFACE:
|
|
@@ -1880,8 +1879,7 @@ unknown:
|
|
|
interface, buf);
|
|
|
if (value < 0)
|
|
|
return value;
|
|
|
-
|
|
|
- value = w_length;
|
|
|
+ value = min_t(u16, w_length, value);
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
@@ -2156,8 +2154,8 @@ int composite_os_desc_req_prepare(struct usb_composite_dev *cdev,
|
|
|
goto end;
|
|
|
}
|
|
|
|
|
|
- /* OS feature descriptor length <= 4kB */
|
|
|
- cdev->os_desc_req->buf = kmalloc(4096, GFP_KERNEL);
|
|
|
+ cdev->os_desc_req->buf = kmalloc(USB_COMP_EP0_OS_DESC_BUFSIZ,
|
|
|
+ GFP_KERNEL);
|
|
|
if (!cdev->os_desc_req->buf) {
|
|
|
ret = -ENOMEM;
|
|
|
usb_ep_free_request(ep0, cdev->os_desc_req);
|