@@ -773,6 +773,33 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (value >= 0)
value = min(w_length, (u16) value);
break;
+
+#ifdef CONFIG_DFU_FUNCTION
+ /* DFU is mighty weird */
+ case DFU_DT_FUNC:
+ w_value &= 0xff;
+ list_for_each_entry(c, &cdev->configs, list) {
+ if (w_value != 0) {
+ w_value--;
+ continue;
+ }
+
+ list_for_each_entry(f, &c->functions, list) {
+
+ /* DFU function only */
+ if (strcmp(f->name, "dfu") != 0)
+ continue;
+
+ value = f->setup(f, ctrl);
+ goto dfu_func_done;
+ }
+ }
+dfu_func_done:
+ if (value >= 0)
+ value = min(w_length, (u16) value);
+ break;
+#endif
+
default:
goto unknown;
}
@@ -221,6 +221,7 @@ static int ep0_get_descriptor (struct usb_device_instance *device,
break;
case USB_DESCRIPTOR_TYPE_CONFIGURATION:
+ case USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION:
{
struct usb_configuration_descriptor
*configuration_descriptor;
@@ -534,8 +534,10 @@ dfu_handle(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
value = min(len, (u16) sizeof(dfu_func));
memcpy(req->buf, &dfu_func, value);
}
- } else /* DFU specific request */
- value = dfu_state[f_dfu->dfu_state] (f_dfu, ctrl, gadget, req);
+ return value;
+ }
+
+ value = dfu_state[f_dfu->dfu_state] (f_dfu, ctrl, gadget, req);
if (value >= 0) {
req->length = value;
DFU is a bit peculiar. It needs to hook to composite setup and return it's function descriptor. So when get-descriptor request comes with a type of DFU_DT_FUNC we iterate over the configs, and functions, and when we find the DFU function we call the setup method which is prepared to return the appropriate function descriptor. Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com> --- drivers/usb/gadget/composite.c | 27 +++++++++++++++++++++++++++ drivers/usb/gadget/ep0.c | 1 + drivers/usb/gadget/f_dfu.c | 6 ++++-- 3 files changed, 32 insertions(+), 2 deletions(-)