void main_subtask_usb_state(void) { static uint64_t fsmstate_on_delay = 0; //Delay timer to be sure USB is actually operating before bringing up hardware uint8_t fsmstate_now = USB->DEVICE.FSMSTATUS.reg; //Current state from hardware register if (fsmstate_now == USB_FSMSTATUS_FSMSTATE_SUSPEND_Val) //If USB SUSPENDED { fsmstate_on_delay = 0; //Clear ON delay timer if (g_usb_state != USB_FSMSTATUS_FSMSTATE_SUSPEND_Val) //If previously not SUSPENDED { suspend_power_down(); //Run suspend routine g_usb_state = fsmstate_now; //Save current USB state } } else if (fsmstate_now == USB_FSMSTATUS_FSMSTATE_SLEEP_Val) //Else if USB SLEEPING { fsmstate_on_delay = 0; //Clear ON delay timer if (g_usb_state != USB_FSMSTATUS_FSMSTATE_SLEEP_Val) //If previously not SLEEPING { suspend_power_down(); //Run suspend routine g_usb_state = fsmstate_now; //Save current USB state } } else if (fsmstate_now == USB_FSMSTATUS_FSMSTATE_ON_Val) //Else if USB ON { if (g_usb_state != USB_FSMSTATUS_FSMSTATE_ON_Val) //If previously not ON { if (fsmstate_on_delay == 0) //If ON delay timer is cleared { fsmstate_on_delay = timer_read64() + 250; //Set ON delay timer } else if (timer_read64() > fsmstate_on_delay) //Else if ON delay timer is active and timed out { suspend_wakeup_init(); //Run wakeup routine g_usb_state = fsmstate_now; //Save current USB state } } } else //Else if USB is in a state not being tracked { fsmstate_on_delay = 0; //Clear ON delay timer } }
/* Handles the USB driver global events * TODO: maybe disable some things when connection is lost? */ static void usb_event_cb(USBDriver *usbp, usbevent_t event) { switch(event) { case USB_EVENT_ADDRESS: return; case USB_EVENT_CONFIGURED: osalSysLockFromISR(); /* Enable the endpoints specified into the configuration. */ usbInitEndpointI(usbp, KEYBOARD_IN_EPNUM, &kbd_ep_config); #ifdef MOUSE_ENABLE usbInitEndpointI(usbp, MOUSE_IN_EPNUM, &mouse_ep_config); #endif /* MOUSE_ENABLE */ #ifdef EXTRAKEY_ENABLE usbInitEndpointI(usbp, EXTRAKEY_IN_EPNUM, &extra_ep_config); #endif /* EXTRAKEY_ENABLE */ #ifdef NKRO_ENABLE usbInitEndpointI(usbp, NKRO_IN_EPNUM, &nkro_ep_config); #endif /* NKRO_ENABLE */ for (int i=0;i<NUM_USB_DRIVERS;i++) { usbInitEndpointI(usbp, drivers.array[i].config.bulk_in, &drivers.array[i].in_ep_config); usbInitEndpointI(usbp, drivers.array[i].config.bulk_out, &drivers.array[i].out_ep_config); if (drivers.array[i].config.int_in) { usbInitEndpointI(usbp, drivers.array[i].config.int_in, &drivers.array[i].int_ep_config); } qmkusbConfigureHookI(&drivers.array[i].driver); } osalSysUnlockFromISR(); return; case USB_EVENT_SUSPEND: #ifdef SLEEP_LED_ENABLE sleep_led_enable(); #endif /* SLEEP_LED_ENABLE */ /* Falls into.*/ case USB_EVENT_UNCONFIGURED: /* Falls into.*/ case USB_EVENT_RESET: for (int i=0;i<NUM_USB_DRIVERS;i++) { chSysLockFromISR(); /* Disconnection event on suspend.*/ qmkusbSuspendHookI(&drivers.array[i].driver); chSysUnlockFromISR(); } return; case USB_EVENT_WAKEUP: //TODO: from ISR! print("[W]"); for (int i=0;i<NUM_USB_DRIVERS;i++) { chSysLockFromISR(); /* Disconnection event on suspend.*/ qmkusbWakeupHookI(&drivers.array[i].driver); chSysUnlockFromISR(); } suspend_wakeup_init(); #ifdef SLEEP_LED_ENABLE sleep_led_disable(); // NOTE: converters may not accept this led_set(host_keyboard_leds()); #endif /* SLEEP_LED_ENABLE */ return; case USB_EVENT_STALLED: return; } }