void DFU_UsbStop (void) { Disable_global_interrupt(); Usb_disable(); (void)Is_usb_enabled(); Enable_global_interrupt(); }
/** * @brief This function initializes the USB controller in host mode and * the associated variables. * * This function enables the USB controller for host mode operation. * * @param none * * @return none * */ void usb_host_task_init(void) { Pll_start_auto(); Wait_pll_ready(); Usb_disable(); Usb_enable(); Usb_unfreeze_clock(); Usb_attach(); Usb_enable_uvcon_pin(); Usb_select_host(); Usb_disable_vbus_hw_control(); // Force Vbus generation without timeout Host_enable_device_disconnection_interrupt(); device_state=DEVICE_UNATTACHED; init_usb_tree(); }
//! //! @brief This function initializes the USB device controller and system interrupt //! //! This function enables the USB controller and init the USB interrupts. //! The aim is to allow the USB connection detection in order to send //! the appropriate USB event to the operating mode manager. //! //! @param none //! //! @return none //! //!/ void usb_device_task_init(void) { Enable_interrupt(); Usb_disable(); Usb_enable(); Usb_select_device(); #if (USB_LOW_SPEED_DEVICE==ENABLE) Usb_low_speed_mode(); #endif Enable_interrupt(); #if (USB_OTG_FEATURE == ENABLED) Usb_enable_id_interrupt(); Clear_otg_features_from_host(); otg_device_sessions = 0; #endif }
//! //! @brief This function initializes the USB host controller. //! //! This function enables the USB controller for host-mode operation. //! void usb_host_task_init(void) { //! @todo Implement this on the silicon version //Pll_start_auto(); //Wait_pll_ready(); cpu_irq_disable(); Usb_disable(); (void)Is_usb_enabled(); cpu_irq_enable(); Usb_disable_otg_pad(); Usb_enable_otg_pad(); Usb_enable(); Usb_unfreeze_clock(); (void)Is_usb_clock_frozen(); #if USB_VBOF_ACTIVE_LEVEL == HIGH Usb_set_vbof_active_high(); #else // USB_VBOF_ACTIVE_LEVEL == LOW Usb_set_vbof_active_low(); #endif Usb_output_vbof_pin(); Usb_disable_vbus_hw_control(); // Force VBus generation without time-out Host_enable_device_disconnection_interrupt(); Host_enable_device_connection_interrupt(); #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE reset_it_pipe_str(); #endif device_state = DEVICE_UNATTACHED; Host_clear_device_status(); Host_ack_request_resume(); sof_cnt = 0; #ifdef FREERTOS_USED xTaskCreate(usb_host_task, configTSK_USB_HST_NAME, configTSK_USB_HST_STACK_SIZE, NULL, configTSK_USB_HST_PRIORITY, &usb_host_tsk); #endif // FREERTOS_USED }
__interrupt #endif static void usb_general_interrupt(void) #endif { #ifdef FREERTOS_USED portBASE_TYPE task_woken = pdFALSE; #endif #if USB_HOST_FEATURE == true && USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE U8 i; #endif // ---------- DEVICE/HOST events management ------------------------------------ #if USB_DEVICE_FEATURE == true && USB_HOST_FEATURE == true // ID pin change detection if (Is_usb_id_transition() && Is_usb_id_interrupt_enabled()) { g_usb_mode = (Is_usb_id_device()) ? USB_MODE_DEVICE : USB_MODE_HOST; Usb_ack_id_transition(); if (g_usb_mode != g_old_usb_mode) // Basic debounce { // Previously in device mode, check if disconnection was detected if (g_old_usb_mode == USB_MODE_DEVICE) { if (usb_connected) { // Device mode disconnection actions usb_connected = false; usb_configuration_nb = 0; Usb_vbus_off_action(); } } // Previously in host mode, check if disconnection was detected else if (Is_host_attached()) { // Host mode disconnection actions device_state = DEVICE_UNATTACHED; Host_device_disconnection_action(); } //LOG_STR(log_pin_id_changed); if (Is_usb_id_device() == USB_MODE_DEVICE) { LOG_STR(log_pin_id_changed_to_device); } else { LOG_STR(log_pin_id_changed_to_host); } Usb_send_event((Is_usb_device()) ? EVT_USB_DEVICE_FUNCTION : EVT_USB_HOST_FUNCTION); Usb_id_transition_action(); // Easier to recover from ID signal de-bounce and ID pin transitions by shutting down the USB and resetting state machine to re-init #if ID_PIN_CHANGE_SHUTDOWN_USB == ENABLE Usb_disable(); Usb_disable_otg_pad(); extern void UsbResetStateMachine(void); UsbResetStateMachine(); #ifdef FREERTOS_USED // Release the semaphore in order to start a new device/host task taskENTER_CRITICAL(); xSemaphoreGiveFromISR(usb_tsk_semphr, &task_woken); taskEXIT_CRITICAL(); #endif #endif #if ID_PIN_CHANGE_GENERATE_RESET == ENABLE Reset_CPU(); #endif } } #endif // End DEVICE/HOST FEATURE MODE // ---------- DEVICE events management ----------------------------------------- #if USB_DEVICE_FEATURE == true #if USB_HOST_FEATURE == true // If both device and host features are enabled, check if device mode is engaged // (accessing the USB registers of a non-engaged mode, even with load operations, // may corrupt USB FIFO data). if (Is_usb_device()) #endif { // VBus state detection if (Is_usb_vbus_transition() && Is_usb_vbus_interrupt_enabled()) { Usb_ack_vbus_transition(); if (Is_usb_vbus_high()) { usb_start_device(); Usb_send_event(EVT_USB_POWERED); Usb_vbus_on_action(); } else { Usb_unfreeze_clock(); Usb_detach(); usb_connected = false; usb_configuration_nb = 0; Usb_send_event(EVT_USB_UNPOWERED); Usb_vbus_off_action(); #ifdef FREERTOS_USED // Release the semaphore in order to start a new device/host task taskENTER_CRITICAL(); xSemaphoreGiveFromISR(usb_tsk_semphr, &task_woken); taskEXIT_CRITICAL(); #endif } } // Device Start-of-Frame received if (Is_usb_sof() && Is_usb_sof_interrupt_enabled()) { Usb_ack_sof(); Usb_sof_action(); } // Device Suspend event (no more USB activity detected) if (Is_usb_suspend() && Is_usb_suspend_interrupt_enabled()) { Usb_ack_suspend(); Usb_enable_wake_up_interrupt(); (void)Is_usb_wake_up_interrupt_enabled(); Usb_freeze_clock(); Usb_send_event(EVT_USB_SUSPEND); Usb_suspend_action(); } // Wake-up event (USB activity detected): Used to resume if (Is_usb_wake_up() && Is_usb_wake_up_interrupt_enabled()) { Usb_unfreeze_clock(); (void)Is_usb_clock_frozen(); Usb_ack_wake_up(); Usb_disable_wake_up_interrupt(); Usb_wake_up_action(); Usb_send_event(EVT_USB_WAKE_UP); } // Resume state bus detection if (Is_usb_resume() && Is_usb_resume_interrupt_enabled()) { Usb_disable_wake_up_interrupt(); Usb_ack_resume(); Usb_disable_resume_interrupt(); Usb_resume_action(); Usb_send_event(EVT_USB_RESUME); } // USB bus reset detection if (Is_usb_reset() && Is_usb_reset_interrupt_enabled()) { Usb_ack_reset(); usb_init_device(); Usb_reset_action(); Usb_send_event(EVT_USB_RESET); } } #endif // End DEVICE FEATURE MODE // ---------- HOST events management ------------------------------------------- #if USB_HOST_FEATURE == true #if USB_DEVICE_FEATURE == true // If both device and host features are enabled, check if host mode is engaged // (accessing the USB registers of a non-engaged mode, even with load operations, // may corrupt USB FIFO data). else #endif { // The device has been disconnected if (Is_host_device_disconnection() && Is_host_device_disconnection_interrupt_enabled()) { host_disable_all_pipes(); Host_ack_device_disconnection(); #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE reset_it_pipe_str(); #endif device_state = DEVICE_UNATTACHED; LOG_STR(log_device_disconnected); Usb_send_event(EVT_HOST_DISCONNECTION); Host_device_disconnection_action(); #ifdef FREERTOS_USED // Release the semaphore in order to start a new device/host task taskENTER_CRITICAL(); xSemaphoreGiveFromISR(usb_tsk_semphr, &task_woken); taskEXIT_CRITICAL(); #endif } // Device connection if (Is_host_device_connection() && Is_host_device_connection_interrupt_enabled()) { Host_ack_device_connection(); host_disable_all_pipes(); Host_device_connection_action(); } // Host Start-of-Frame has been sent if (Is_host_sof() && Is_host_sof_interrupt_enabled()) { Host_ack_sof(); Usb_send_event(EVT_HOST_SOF); #if (USB_HIGH_SPEED_SUPPORT==true) if( Is_usb_full_speed_mode() ) { private_sof_counter++; }else{ private_sof_counter_HS++; if( 0 == (private_sof_counter_HS%8) ) { private_sof_counter++; } } #else private_sof_counter++; #endif // Delay time-out management for interrupt transfer mode in host mode #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE && TIMEOUT_DELAY_ENABLE == ENABLE if (private_sof_counter >= 250) // Count 250 ms (SOF @ 1 ms) { private_sof_counter = 0; for (i = 0; i < MAX_PEP_NB; i++) { if (it_pipe_str[i].enable && ++it_pipe_str[i].timeout > TIMEOUT_DELAY && Host_get_pipe_type(i) != TYPE_INTERRUPT) { it_pipe_str[i].enable = false; it_pipe_str[i].status = PIPE_DELAY_TIMEOUT; Host_reset_pipe(i); if (!is_any_interrupt_pipe_active() && !g_sav_int_sof_enable) // If no more transfer is armed { Host_disable_sof_interrupt(); } it_pipe_str[i].handler(PIPE_DELAY_TIMEOUT, it_pipe_str[i].nb_byte_processed); } } } #endif Host_sof_action(); } // Host Wake-up has been received if (Is_host_hwup() && Is_host_hwup_interrupt_enabled()) { // CAUTION: HWUP can be cleared only when USB clock is active (not frozen)! //! @todo Implement this on the silicon version //Pll_start_auto(); // First Restart the PLL for USB operation //Wait_pll_ready(); // Make sure PLL is locked Usb_unfreeze_clock(); // Enable clock on USB interface (void)Is_usb_clock_frozen(); // Make sure USB interface clock is enabled Host_disable_hwup_interrupt(); // Wake-up interrupt should be disabled as host is now awoken! Host_ack_hwup(); // Clear HWUP interrupt flag Usb_send_event(EVT_HOST_HWUP); // Send software event Host_hwup_action(); // Map custom action } #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE // Host pipe interrupts while ((i = Host_get_interrupt_pipe_number()) < MAX_PEP_NB) usb_pipe_interrupt(i); #endif } #endif // End HOST FEATURE MODE #ifdef FREERTOS_USED return task_woken; #endif }
ISR(usb_general_interrupt, AVR32_USBB_IRQ_GROUP, USB_INT_LEVEL) #endif { #ifdef FREERTOS_USED portBASE_TYPE task_woken = pdFALSE; #endif uint8_t i; /* avoid Cppcheck Warning */ UNUSED(i); // ---------- DEVICE/HOST events management ------------------------------------ #if USB_DEVICE_FEATURE == true && USB_HOST_FEATURE == true // ID pin change detection if (Is_usb_id_transition() && Is_usb_id_interrupt_enabled()) { g_usb_mode = (Is_usb_id_device()) ? USB_MODE_DEVICE : USB_MODE_HOST; Usb_ack_id_transition(); if (g_usb_mode != g_old_usb_mode) // Basic debounce { // Previously in device mode, check if disconnection was detected if (g_old_usb_mode == USB_MODE_DEVICE) { if (usb_connected) { // Device mode diconnection actions usb_connected = false; usb_configuration_nb = 0; Usb_vbus_off_action(); } } // Previously in host mode, check if disconnection was detected else if (Is_host_attached()) { // Host mode diconnection actions device_state = DEVICE_UNATTACHED; Host_device_disconnection_action(); } LOG_STR(log_pin_id_changed); Usb_send_event((Is_usb_device()) ? EVT_USB_DEVICE_FUNCTION : EVT_USB_HOST_FUNCTION); Usb_id_transition_action(); //! @todo ID pin hot state change!!! // Preliminary management: HARDWARE RESET!!! #if ID_PIN_CHANGE_GENERATE_RESET == ENABLE // Hot ID transition generates CPU reset Usb_disable(); Usb_disable_otg_pad(); #ifdef FREERTOS_USED // Release the semaphore in order to start a new device/host task taskENTER_CRITICAL(); xSemaphoreGiveFromISR(usb_tsk_semphr, &task_woken); taskEXIT_CRITICAL(); #else #if defined(CPU_RESET_CALLBACK) CPU_RESET_CALLBACK(); #endif Reset_CPU(); #endif #endif g_old_usb_mode = g_usb_mode; // Store current USB mode, for mode change detection } } #endif // End DEVICE/HOST FEATURE MODE // ---------- DEVICE events management ----------------------------------------- #if USB_DEVICE_FEATURE == true #if USB_HOST_FEATURE == true // If both device and host features are enabled, check if device mode is engaged // (accessing the USB registers of a non-engaged mode, even with load operations, // may corrupt USB FIFO data). if (Is_usb_device()) #endif { // VBus state detection if (Is_usb_vbus_transition() && Is_usb_vbus_interrupt_enabled()) { Usb_ack_vbus_transition(); if (Is_usb_vbus_high()) { usb_start_device(); Usb_send_event(EVT_USB_POWERED); Usb_vbus_on_action(); } else { Usb_unfreeze_clock(); Usb_detach(); usb_connected = false; usb_configuration_nb = 0; Usb_send_event(EVT_USB_UNPOWERED); Usb_vbus_off_action(); #ifdef FREERTOS_USED // Release the semaphore in order to start a new device/host task taskENTER_CRITICAL(); xSemaphoreGiveFromISR(usb_tsk_semphr, &task_woken); taskEXIT_CRITICAL(); #endif } } // Device Start-of-Frame received if (Is_usb_sof() && Is_usb_sof_interrupt_enabled()) { Usb_ack_sof(); Usb_sof_action(); } // Device Suspend event (no more USB activity detected) if (Is_usb_suspend() && Is_usb_suspend_interrupt_enabled()) { Usb_ack_suspend(); Usb_enable_wake_up_interrupt(); (void)Is_usb_wake_up_interrupt_enabled(); Usb_freeze_clock(); Usb_send_event(EVT_USB_SUSPEND); Usb_suspend_action(); } // Wake-up event (USB activity detected): Used to resume if (Is_usb_wake_up() && Is_usb_wake_up_interrupt_enabled()) { Usb_unfreeze_clock(); (void)Is_usb_clock_frozen(); Usb_ack_wake_up(); Usb_disable_wake_up_interrupt(); Usb_wake_up_action(); Usb_send_event(EVT_USB_WAKE_UP); } // Resume state bus detection if (Is_usb_resume() && Is_usb_resume_interrupt_enabled()) { Usb_disable_wake_up_interrupt(); Usb_ack_resume(); Usb_disable_resume_interrupt(); Usb_resume_action(); Usb_send_event(EVT_USB_RESUME); } // USB bus reset detection if (Is_usb_reset() && Is_usb_reset_interrupt_enabled()) { Usb_ack_reset(); usb_init_device(); Usb_reset_action(); Usb_send_event(EVT_USB_RESET); } } #endif // End DEVICE FEATURE MODE // ---------- HOST events management ------------------------------------------- #if USB_HOST_FEATURE == true #if USB_DEVICE_FEATURE == true // If both device and host features are enabled, check if host mode is engaged // (accessing the USB registers of a non-engaged mode, even with load operations, // may corrupt USB FIFO data). else #endif { // The device has been disconnected if (Is_host_device_disconnection() && Is_host_device_disconnection_interrupt_enabled()) { host_disable_all_pipes(); Host_ack_device_disconnection(); #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE reset_it_pipe_str(); #endif #ifdef HOST_VBUS_LOW_TIMEOUT cpu_set_timeout(HOST_VBUS_LOW_TIMEOUT, &timer_vbus_low); device_state = DEVICE_VBUS_LOW; #else device_state = DEVICE_UNATTACHED; #endif LOG_STR(log_device_disconnected); Usb_send_event(EVT_HOST_DISCONNECTION); Host_device_disconnection_action(); #ifdef FREERTOS_USED // Release the semaphore in order to start a new device/host task taskENTER_CRITICAL(); xSemaphoreGiveFromISR(usb_tsk_semphr, &task_woken); taskEXIT_CRITICAL(); #endif } // Device connection if (Is_host_device_connection() && Is_host_device_connection_interrupt_enabled()) { Host_ack_device_connection(); host_disable_all_pipes(); Usb_send_event(EVT_HOST_CONNECTION); Host_device_connection_action(); } // Host Start-of-Frame has been sent if (Is_host_sof() && Is_host_sof_interrupt_enabled()) { Host_ack_sof(); Usb_send_event(EVT_HOST_SOF); private_sof_counter++; // Delay time-out management for interrupt tranfer mode in host mode #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE && TIMEOUT_DELAY_ENABLE == ENABLE if (private_sof_counter >= 250) // Count 250 ms (SOF @ 1 ms) { private_sof_counter = 0; for (i = 0; i < MAX_PEP_NB; i++) { if (it_pipe_str[i].enable && ++it_pipe_str[i].timeout > TIMEOUT_DELAY && Host_get_pipe_type(i) != TYPE_INTERRUPT) { it_pipe_str[i].enable = false; it_pipe_str[i].status = PIPE_DELAY_TIMEOUT; Host_reset_pipe(i); if (!is_any_interrupt_pipe_active() && !g_sav_int_sof_enable) // If no more transfer is armed { Host_disable_sof_interrupt(); } it_pipe_str[i].handler(PIPE_DELAY_TIMEOUT, it_pipe_str[i].nb_byte_processed); } } } #endif Host_sof_action(); } // Host Wake-up has been received if (Is_host_hwup() && Is_host_hwup_interrupt_enabled()) { // CAUTION: HWUP can be cleared only when USB clock is active (not frozen)! //! @todo Implement this on the silicon version //Pll_start_auto(); // First Restart the PLL for USB operation //Wait_pll_ready(); // Make sure PLL is locked Usb_unfreeze_clock(); // Enable clock on USB interface (void)Is_usb_clock_frozen(); // Make sure USB interface clock is enabled Host_disable_hwup_interrupt(); // Wake-up interrupt should be disabled as host is now awoken! Host_ack_hwup(); // Clear HWUP interrupt flag Usb_send_event(EVT_HOST_HWUP); // Send software event Host_hwup_action(); // Map custom action } Host_int_action(); while ((i = Host_get_interrupt_pipe_number()) < MAX_PEP_NB) { if (Is_host_in_received(i) && Is_host_in_received_interrupt_enabled(i)) { Host_freeze_pipe(i); Host_disable_in_received_interrupt(i); } } #if defined(USB_HIGH_SPEED_SUPPORT) && USB_HIGH_SPEED_SUPPORT == true && \ defined(PIPE_AUDIO_IN) // Workaround - freeze the IN audio pipe if (Is_host_in_received(PIPE_AUDIO_IN)) { extern void workaround_freeze_iso_in(void); workaround_freeze_iso_in(); } #endif // USB_HIGH_SPEED_SUPPORT == true #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE // Host pipe interrupts while ((i = Host_get_interrupt_pipe_number()) < MAX_PEP_NB) usb_pipe_interrupt(i); #endif } #endif // End HOST FEATURE MODE #ifdef FREERTOS_USED return task_woken; #endif }
/** * @brief Entry point of the USB mamnagement * * Depending on the USB mode supported (HOST/DEVICE/DUAL_ROLE) the function * calls the coresponding usb management function. * * @param none * * @return none */ void usb_task(void) { // ---- DUAL ROLE DEVICE USB MODE --------------------------------------------- #if ((USB_DEVICE_FEATURE == ENABLED)&& (USB_HOST_FEATURE == ENABLED)) if(Is_usb_id_device()) { g_usb_mode=USB_MODE_DEVICE;} else { g_usb_mode=USB_MODE_HOST;} if( g_old_usb_mode != g_usb_mode ) { // ID pin hot state change #if ( ID_PIN_CHANGE_GENERATE_RESET == ENABLE) // Hot ID transition generates wdt reset wdtdrv_enable(WDTO_16MS); while(1); #else // Hot ID transition reset USB mode Usb_ack_id_transition(); // REQUIRED if (Is_usb_id_host()) { Usb_disable_resume_interrupt(); Usb_disable_wake_up_interrupt(); Usb_disable_suspend_interrupt(); Usb_disable_reset_interrupt(); Usb_detach(); Usb_disable(); usb_host_task_init(); } else { Host_disable_device_disconnection_interrupt(); Host_disable_sof_interrupt(); Host_disable_sof(); Usb_disable_vbus(); Usb_disable_manual_vbus(); Usb_freeze_clock(); Usb_disable(); usb_device_task_init(); } #endif } // Store current usb mode, for mode change detection g_old_usb_mode=g_usb_mode; // Depending on current usb mode, launch the correct usb task (device or host) switch(g_usb_mode) { case USB_MODE_DEVICE: usb_device_task(); break; case USB_MODE_HOST: usb_host_task(); break; case USB_MODE_UNDEFINED: // No break ! default: break; } // ----------------------------------------------------------------------------- // ---- DEVICE ONLY USB MODE --------------------------------------------------- #elif ((USB_DEVICE_FEATURE == ENABLED)&& (USB_HOST_FEATURE == DISABLE)) usb_device_task(); // ----------------------------------------------------------------------------- // ---- REDUCED HOST ONLY USB MODE --------------------------------------------- #elif ((USB_DEVICE_FEATURE == DISABLE)&& (USB_HOST_FEATURE == ENABLED)) usb_host_task(); // ----------------------------------------------------------------------------- //! ---- ERROR, NO MODE ENABLED ------------------------------------------------- #elif ((USB_DEVICE_FEATURE == DISABLE)&& (USB_HOST_FEATURE == DISABLE)) #error at least one of USB_DEVICE_FEATURE or USB_HOST_FEATURE should be enabled #error otherwise the usb task has nothing to do ... #endif // ----------------------------------------------------------------------------- }
//! @brief Entry point of the USB device mamagement //! //! This function is the entry point of the USB management. Each USB //! event is checked here in order to launch the appropriate action. //! If a Setup request occurs on the Default Control Endpoint, //! the usb_process_request() function is call in the usb_standard_request.c file //! //! @param none //! //! @return none void usb_device_task(void) { #if (USB_OTG_FEATURE == ENABLED) // Check if a reset has been received if(Is_usb_event(EVT_USB_RESET)) { Usb_ack_event(EVT_USB_RESET); Usb_reset_endpoint(0); usb_configuration_nb=0; otg_b_device_state = B_IDLE; Clear_otg_features_from_host(); } // When OTG mode enabled, B-Device is managed thanks to its state machine switch (otg_b_device_state) { //------------------------------------------------------ // B_IDLE state // // - waits for Vbus to rise // - initiate SRP if asked by user // case B_IDLE: if (Is_usb_vbus_high()) { // Vbus rise usb_connected = TRUE; remote_wakeup_feature = DISABLED; usb_start_device(); Usb_vbus_on_action(); Usb_attach(); otg_b_device_state = B_PERIPHERAL; Ack_user_request_srp(); Clear_otg_features_from_host(); remote_wakeup_feature = DISABLED; End_session_with_srp(); if (Is_srp_sent_and_waiting_answer() && (sof_seen_in_session == TRUE)) { Ack_srp_sent_and_answer(); Otg_print_new_failure_message(OTGMSG_A_RESPONDED,OTG_TEMPO_2SEC); } Usb_enable_sof_interrupt(); } else { if (Is_user_requested_srp() && Is_usb_id_device()) { // User has requested a SRP Ack_user_request_srp(); if (!Is_srp_sent_and_waiting_answer()) { Pll_start_auto(); // reinit device mode Wait_pll_ready(); Usb_disable(); Usb_enable_uid_pin(); Usb_enable(); Usb_unfreeze_clock(); Usb_select_device(); Usb_attach(); otg_b_device_state = B_SRP_INIT; Usb_device_initiate_srp(); // hardware waits for initial condition (SE0, Session End level) sof_seen_in_session = FALSE; } } if ((Is_srp_sent_and_waiting_answer()) && (Is_tb_srp_counter_overflow())) { // SRP failed because A-Device did not respond End_session_with_srp(); Ack_srp_sent_and_answer(); Otg_print_new_failure_message(OTGMSG_SRP_A_NO_RESP,OTG_TEMPO_3SEC); } } break; //------------------------------------------------------ // B_SRP_INIT // // - a SRP has been initiated // - B-Device waits it is finished to initialize variables // case B_SRP_INIT: if (!Is_usb_device_initiating_srp()) { otg_b_device_state = B_IDLE; // SRP initiated, return to Idle state (wait for Vbus to rise) Srp_sent_and_waiting_answer(); Init_tb_srp_counter(); Start_session_with_srp(); Otg_print_new_event_message(OTGMSG_SRP_STARTED,TB_SRP_FAIL_MIN); } break; //------------------------------------------------------ // B_PERIPHERAL : the main state of OTG Peripheral // // - all events are interrupt-handled // - but they are saved and this function can execute alternate actions // - also handle user requests (disconnect) // // ====================================================================================== case B_PERIPHERAL: if (Is_otg_event(EVT_OTG_DEVICE_CONNECTED)) { Otg_ack_event(EVT_OTG_DEVICE_CONNECTED); // set on a SetConfiguration descriptor reception Otg_print_new_event_message(OTGMSG_CONNECTED_TO_A,OTG_TEMPO_4SEC); } if (Is_usb_event(EVT_USB_SUSPEND)) // SUSPEND state { // Suspend and HNP operations are handled in the interrupt functions } if (Is_srp_sent_and_waiting_answer() && (sof_seen_in_session == TRUE)) { Ack_srp_sent_and_answer(); Otg_print_new_failure_message(OTGMSG_A_RESPONDED,OTG_TEMPO_2SEC); } if ((Is_srp_sent_and_waiting_answer()) && (Is_tb_srp_counter_overflow())) { // SRP failed because A-Device did not respond End_session_with_srp(); Ack_srp_sent_and_answer(); Otg_print_new_failure_message(OTGMSG_SRP_A_NO_RESP,OTG_TEMPO_3SEC); } if (Is_usb_event(EVT_USB_RESUME) && !Is_usb_pending_remote_wake_up()) // RESUME signal detected { Usb_ack_event(EVT_USB_RESUME); Usb_ack_event(EVT_USB_SUSPEND); Usb_ack_remote_wake_up_start(); } if (Is_usb_event(EVT_USB_UNPOWERED)) { Usb_ack_event(EVT_USB_UNPOWERED); Clear_all_user_request(); otg_b_device_state = B_IDLE; } if(Is_usb_event(EVT_USB_RESET)) { Usb_ack_event(EVT_USB_RESET); Usb_reset_endpoint(0); usb_configuration_nb=0; Clear_otg_features_from_host(); } if (Is_otg_event(EVT_OTG_HNP_ERROR)) { Otg_ack_event(EVT_OTG_HNP_ERROR); Otg_print_new_failure_message(OTGMSG_DEVICE_NO_RESP,OTG_TEMPO_4SEC); PORTC &= ~0x10; } if (Is_user_requested_disc()) { Ack_user_request_disc(); if (Is_usb_id_device()) { Usb_detach(); Usb_freeze_clock(); while (Is_usb_vbus_high()); // wait for Vbus to be under Va_vbus_valid otg_b_device_state = B_IDLE; usb_configuration_nb = 0; usb_connected = FALSE; Clear_all_user_request(); } } break; //------------------------------------------------------ // B_HOST // // - state entered after an HNP success // - handle user requests (disconnection, suspend, hnp) // - call the "host_task()" for Host level handlers // // ====================================================================================== case B_HOST: if (Is_otg_event(EVT_OTG_DEV_UNSUPPORTED)) { Otg_ack_event(EVT_OTG_DEV_UNSUPPORTED); Clear_all_user_request(); otg_b_device_state = B_IDLE; device_state = DEVICE_UNATTACHED; } if (Is_user_requested_disc() || Is_user_requested_suspend() || Is_user_requested_hnp()) { Ack_user_request_disc(); // suspend and hnp requests cleared in B_END_HNP_SUSPEND stage Host_disable_sof(); // go into suspend mode Usb_host_reject_hnp(); otg_b_device_state = B_END_HNP_SUSPEND; Usb_ack_suspend(); Usb_enable_suspend_interrupt(); } if (Is_usb_event(EVT_USB_UNPOWERED)) { Usb_ack_event(EVT_USB_UNPOWERED); Usb_freeze_clock(); otg_b_device_state = B_IDLE; device_state = DEVICE_UNATTACHED; } usb_host_task(); // call the host task break; //------------------------------------------------------ // B_END_HNP_SUSPEND // // - device enters this state after being B_HOST, on a user request to stop bus activity (suspend, disconnect or hnp request) // - macro is reset to peripheral mode // // ====================================================================================== case B_END_HNP_SUSPEND: if (Is_usb_event(EVT_USB_SUSPEND)) { Usb_ack_event(EVT_USB_SUSPEND); Usb_device_stop_hnp(); Usb_select_device(); device_state = DEVICE_UNATTACHED; if (Is_user_requested_hnp() || Is_user_requested_suspend()) { otg_b_device_state = B_PERIPHERAL; Ack_user_request_suspend(); Ack_user_request_hnp(); } else { otg_b_device_state = B_IDLE; Usb_detach(); Usb_freeze_clock(); } } break; default: otg_b_device_state = B_IDLE; Clear_all_user_request(); device_state = DEVICE_UNATTACHED; break; } #else // Non-OTG exclusives Device operations // VBUS state detection if (Is_usb_vbus_high()&& (usb_connected==FALSE)) { usb_connected = TRUE; remote_wakeup_feature = DISABLED; Usb_vbus_on_action(); Usb_send_event(EVT_USB_POWERED); usb_start_device(); } if (Is_usb_vbus_low()&& (usb_connected==TRUE)) { usb_connected = FALSE; usb_configuration_nb = 0; Usb_send_event(EVT_USB_UNPOWERED); Usb_detach(); Usb_freeze_clock(); Usb_vbus_off_action(); } if(Is_usb_event(EVT_USB_RESET)) { Usb_ack_event(EVT_USB_RESET); Usb_reset_endpoint(0); usb_configuration_nb=0; } #endif // ======================================= // Common Standard Device Control Requests // ======================================= // - device enumeration process // - device control commands and features Usb_select_endpoint(EP_CONTROL); if (Is_usb_receive_setup()) { usb_process_request(); } }