main: add callbacks for discrete USB states

We can save more power by parking threads when suspended, and threads
should be deleted when disconnected.

Also fix an inefficiency in usb_thread wakeups when the device is yet to
be configured, but is addressed - slowing down control transfers.

Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
diff --git a/src/main.c b/src/main.c
index 5204d69..90db00b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -75,8 +75,11 @@
         else
             gpio_put(PROBE_USB_CONNECTED_LED, 0);
 #endif
+        // If suspended or disconnected, delay for 1ms (20 ticks)
+        if (tud_suspended() || !tud_connected())
+            xTaskDelayUntil(&wake, 20);
         // Go to sleep for up to a tick if nothing to do
-        if (!tud_task_event_ready())
+        else if (!tud_task_event_ready())
             xTaskDelayUntil(&wake, 1);
     } while (1);
 }
@@ -189,6 +192,40 @@
 }
 #endif
 
+void tud_suspend_cb(bool remote_wakeup_en)
+{
+  probe_info("Suspended\n");
+  /* Join DAP and UART threads? Or just suspend them, for transparency */
+  vTaskSuspend(uart_taskhandle);
+  vTaskSuspend(dap_taskhandle);
+  /* slow down clk_sys for power saving ? */
+}
+
+void tud_resume_cb(void)
+{
+  probe_info("Resumed\n");
+  vTaskResume(uart_taskhandle);
+  vTaskResume(dap_taskhandle);
+}
+
+void tud_unmount_cb(void)
+{
+  probe_info("Disconnected\n");
+  vTaskSuspend(uart_taskhandle);
+  vTaskSuspend(dap_taskhandle);
+  vTaskDelete(uart_taskhandle);
+  vTaskDelete(dap_taskhandle);
+}
+
+void tud_mount_cb(void)
+{
+  probe_info("Connected, Configured\n");
+  /* UART needs to preempt USB as if we don't, characters get lost */
+  xTaskCreate(cdc_thread, "UART", configMINIMAL_STACK_SIZE, NULL, UART_TASK_PRIO, &uart_taskhandle);
+  /* Lowest priority thread is debug - need to shuffle buffers before we can toggle swd... */
+  xTaskCreate(dap_thread, "DAP", configMINIMAL_STACK_SIZE, NULL, DAP_TASK_PRIO, &dap_taskhandle);
+}
+
 void vApplicationTickHook (void)
 {
 };