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 <pa...@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(-)

diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index ebb5131..6496436 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -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;
                }
diff --git a/drivers/usb/gadget/ep0.c b/drivers/usb/gadget/ep0.c
index aa8f916..971d846 100644
--- a/drivers/usb/gadget/ep0.c
+++ b/drivers/usb/gadget/ep0.c
@@ -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;
diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
index 10547e3..6494f5e 100644
--- a/drivers/usb/gadget/f_dfu.c
+++ b/drivers/usb/gadget/f_dfu.c
@@ -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;
-- 
1.7.12

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to