USB DFU: keep usb connected while we respond to reset request.
authorMichael Moon <triffid.hunter@gmail.com>
Wed, 16 Jan 2013 16:30:20 +0000 (03:30 +1100)
committerMichael Moon <triffid.hunter@gmail.com>
Fri, 18 Jan 2013 03:09:45 +0000 (14:09 +1100)
we also become a kernel module so we can receive the on idle event. This would be an ideal place to do shutdown tasks, eg save position somewhere

src/libs/USBDevice/DFU.cpp
src/libs/USBDevice/DFU.h
src/main.cpp

index bcfeaee..7927d2b 100644 (file)
@@ -39,6 +39,8 @@ DFU::DFU(USB *u)
     usb->addInterface(&dfu_interface);
     usb->addDescriptor(&dfu_descriptor);
     dfu_interface.iInterface = usb->addString(&dfu_string);
+
+    prep_for_detach = 0;
 }
 
 bool DFU::USBEvent_Request(CONTROL_TRANSFER &control)
@@ -48,10 +50,11 @@ bool DFU::USBEvent_Request(CONTROL_TRANSFER &control)
     {
         case  DFU_DETACH:
         {
-            usb->disconnect();
+//             usb->disconnect();
+            prep_for_detach = 128;
             WDT_Init(WDT_CLKSRC_IRC, WDT_MODE_RESET);
-            WDT_Start(1000000); // 1 second?
-//             for (;;);
+            WDT_Start(250000); // 0.25 seconds
+            //             for (;;);
             return true;
         }
         case DFU_GETSTATUS:
@@ -92,3 +95,21 @@ bool DFU::USBEvent_RequestComplete(CONTROL_TRANSFER &control, uint8_t *buf, uint
 {
     return false;
 }
+
+void DFU::on_module_loaded()
+{
+    register_for_event(ON_IDLE);
+}
+
+void DFU::on_idle(void* argument)
+{
+    if (prep_for_detach)
+    {
+        prep_for_detach--;
+        if (prep_for_detach == 0)
+        {
+            usb->disconnect();
+            for (;;);
+        }
+    }
+}
index f5fedc0..2241b31 100644 (file)
@@ -7,6 +7,8 @@
 #include "USBDescriptor.h"
 #include "USBDevice_Types.h"
 
+#include "Module.h"
+
 #include <stdint.h>
 
 #define REQ_DFU_DETACH      0x0
@@ -61,13 +63,16 @@ typedef struct __attribute__ ((packed))
 } DFU_Status_Response;
 
 
-class DFU : public USB_Class_Receiver {
+class DFU : public USB_Class_Receiver, public Module {
 public:
     DFU(USB *);
 
     virtual bool USBEvent_Request(CONTROL_TRANSFER&);
     virtual bool USBEvent_RequestComplete(CONTROL_TRANSFER&, uint8_t *buf, uint32_t length);
 
+    void on_module_loaded(void);
+    void on_idle(void*);
+
 protected:
     USB *usb;
 
@@ -77,6 +82,8 @@ protected:
     usbdesc_string_l(12)        dfu_string;
 
     DFU_Status_Response         dfu_status;
+
+    int prep_for_detach;
 };
 
 #endif /* _DFU_H */
index a192d36..c160c54 100644 (file)
@@ -117,6 +117,7 @@ int main() {
     kernel->add_module( &msc );
     kernel->add_module( &usbserial );
     kernel->add_module( &usbserial2 );
+    kernel->add_module( &dfu );
     kernel->add_module( &u );
 
     struct SerialMessage message;