Ejemplo n.º 1
0
/*FUNCTION*-------------------------------------------------------------
*
*  Function Name  : _usb_otg_khci_isr
*  Returned Value : None
*  Comments       :
*        Service all the interrupts in the kirin usb hardware
*END*-----------------------------------------------------------------*/
static void _usb_otg_khci_isr
(
    void* otg_khci_call_ptr
)
{
    usb_otg_state_struct_t * usb_otg_struct_ptr = ((usb_otg_khci_call_struct_t *)otg_khci_call_ptr)->otg_handle_ptr;

    if (usb_otg_struct_ptr != NULL)
    {
        uint8_t otg_int_stat          = (uint8_t)usb_hal_khci_get_otg_interrupt_status(g_usb_instance.instance);
        uint8_t otg_stat              = usb_hal_khci_get_otg_status(g_usb_instance.instance);
        usb_otg_status_t *otg_status  = &usb_otg_struct_ptr->otg_status;
        /* Handle otg interrupt*/
        if (otg_int_stat != 0)
        {
            /* Clear the OTG relevant interrupts */
            usb_hal_khci_clr_otg_interrupt(g_usb_instance.instance,otg_int_stat);
            if (otg_int_stat & USB_OTGISTAT_ONEMSEC_MASK)
            {          
                otg_status->tmr_1ms  = TRUE; 
                if ( otg_status->ms_since_line_changed < 0xffff )
                {
                    otg_status->ms_since_line_changed++;
                }
                if ( otg_status->host_req_poll_timer < 0xffff )
                {
                    otg_status->host_req_poll_timer++;
                } 
                /* Decrement timeouts */
                if (otg_status->b_timeout_en && otg_status->b_timeout)
                {
                    otg_status->b_timeout--;
                    if (!otg_status->b_timeout)
                    {
                        otg_status->b_timeout_en = FALSE;
                    }
                }
            }
            if ((otg_int_stat & USB_OTGISTAT_LINE_STATE_CHG_MASK) || (!(otg_stat & USB_OTGSTAT_LINESTATESTABLE_MASK)))
            {          
                otg_status->ms_since_line_changed = 0;
            }
        } 
        /* Check active stack*/
        if (otg_status->active_stack == USB_ACTIVE_STACK_HOST)
        {
            /* Host stack is current active stack */
            /* Call function to handle host interrupt*/
            _usb_host_khci_isr(NULL);
        }
        else if (otg_status->active_stack == USB_ACTIVE_STACK_DEVICE)
        {
            /* Device stack is current active stack */
            /* Call function to handle device interrupt*/
           if (usb_otg_struct_ptr->dev_inst_ptr != NULL)
           {
                _usb_dev_khci_isr(usb_otg_struct_ptr->dev_inst_ptr);
           }
           
        }
        else
        {
            /* Clear all pending USB interrupt*/
            usb_hal_khci_clr_all_interrupts(g_usb_instance.instance);
        }
        OS_Event_set(usb_otg_struct_ptr->otg_isr_event, USB_OTG_KHCI_ISR_EVENT);
    }
}
Ejemplo n.º 2
0
/*FUNCTION*----------------------------------------------------------------
*
* Function Name  : App_OtgCallback
* Returned Value : none
* Comments       :
*
*
*END*--------------------------------------------------------------------*/
void App_OtgCallback(usb_otg_handle handle, uint32_t event)
{
    (void)handle; /* not used */

    if (event & OTG_B_IDLE)
    {
        g_dev_type = dev_b;               /* Device type: B */
        g_sess_vld = FALSE;               /* session not valid */
        g_otg_state = OTG_B_IDLE;
    }

    if (event & OTG_B_IDLE_SRP_READY)
    {
        g_otg_state = OTG_B_IDLE_SRP_READY;
    }
    if (event & OTG_B_PERIPHERAL)
    {
        g_otg_state = OTG_B_PERIPHERAL;
        if (g_sess_vld == FALSE)
        {
            g_sess_vld = TRUE;                /* session valid */
        }
    }
    if (event & OTG_B_HOST)
    {
        g_otg_state = OTG_B_HOST;
    }
    if (event & OTG_B_A_HNP_REQ)
    {
        (void)_usb_otg_bus_release(g_otg_handle);
    }
    if (event & OTG_A_WAIT_BCON_TMOUT)
    {
        _usb_otg_set_a_bus_req(g_otg_handle , FALSE);
    }
    if (event & OTG_A_BIDL_ADIS_TMOUT)
    {
        _usb_otg_set_a_bus_req(g_otg_handle, TRUE);
    }
    if (event & OTG_A_B_HNP_REQ)
    {
        _usb_otg_set_a_bus_req( handle , FALSE);
    }
    if (event & OTG_A_IDLE)
    {
        g_dev_type = dev_a;                 /* Device type: A */
        g_sess_vld = FALSE;
        g_otg_state = OTG_A_IDLE;
    }
    if (event & OTG_A_WAIT_VRISE)
    {
        g_otg_state = OTG_A_WAIT_VRISE;
        _usb_otg_set_a_bus_req( handle , TRUE);
    }
    if (event & OTG_A_WAIT_BCON)
    {
        g_sess_vld = TRUE;
        g_otg_state = OTG_A_WAIT_BCON;
    }
    if (event & OTG_A_HOST)
    {
        g_otg_state = OTG_A_HOST;
    }
    if (event & OTG_A_SUSPEND)
    {
        g_otg_state = OTG_A_SUSPEND;
    }
    if (event & OTG_A_PERIPHERAL)
    {
        g_otg_state = OTG_A_PERIPHERAL;
    }
    if (event & OTG_A_WAIT_VFALL)
    {
        if (g_vbus_err == TRUE)
        {
            g_vbus_err = FALSE;
        }
        g_otg_state = OTG_A_WAIT_VFALL;
    }
    if (event & OTG_A_VBUS_ERR)
    {
        g_vbus_err = TRUE;
        g_otg_state = OTG_A_VBUS_ERR;
    }
    OS_Event_set(g_otg_app_event_handle, event);
}
Ejemplo n.º 3
0
/*FUNCTION*----------------------------------------------------------------
*
* Function Name  : usb_host_hid_keyboard_event
* Returned Value : None
* Comments       :
*     Called when HID device has been attached, detached, etc.
*END*--------------------------------------------------------------------*/
void usb_host_hid_keyboard_event(
/* [IN] pointer to device instance */
usb_device_instance_handle dev_handle,
/* [IN] pointer to interface descriptor */
usb_interface_descriptor_handle intf_handle,
/* [IN] code number for event causing callback */
uint32_t event_code)
{
    usb_device_interface_struct_t* pHostIntf = (usb_device_interface_struct_t*)intf_handle;
    interface_descriptor_t* intf_ptr = pHostIntf->lpinterfaceDesc;
    usb_status status = USB_OK;
	 
    //fflush(stdout);
    switch (event_code) {
        case USB_ATTACH_EVENT:
            g_interface_info[g_interface_number] = pHostIntf;
            g_interface_number++;
            printf("HID State = %d", g_kbd_hid_device.dev_state);
            printf("HID  Class = %d", intf_ptr->bInterfaceClass);
            printf("HID  SubClass = %d", intf_ptr->bInterfaceSubClass);
            printf("HID  Protocol = %d\n", intf_ptr->bInterfaceProtocol);
            break;
            /* Drop through config event for the same processing */
        case USB_CONFIG_EVENT:
            //fflush(stdout);
            printf("HID State = USB_CONFIG_EVENT");
            if(g_kbd_hid_device.dev_state == USB_DEVICE_IDLE) 
            {
                g_kbd_hid_device.dev_handle = dev_handle;
                g_kbd_hid_device.intf_handle = hid_get_interface();;
                g_kbd_hid_device.dev_state = USB_DEVICE_CONFIGURED;
            }
            else
            {
                printf("HID device already attached\n");
                //fflush(stdout);
            }
            break;
    	case USB_INTF_OPENED_EVENT:
            printf("HID State = USB_INTF_OPENED_EVENT");
            g_kbd_hid_device.dev_state = USB_DEVICE_INTERFACED;
            OS_Event_set(usb_keyboard_event, USB_Keyboard_Event_CTRL);
            break;
    	  
        case USB_DETACH_EVENT:
            /* Use only the interface with desired protocol */
            g_interface_number = 0;
			if (g_kbd_hid_device.dev_state < USB_DEVICE_INTERFACED)
			{
				g_kbd_hid_device.dev_handle = NULL;
				g_kbd_hid_device.intf_handle = NULL;
				g_kbd_hid_device.dev_state = USB_DEVICE_IDLE;
				return;
			}
            printf("\n----- Detach Event -----\n");
            printf("State = %d", g_kbd_hid_device.dev_state);
            printf("  Class = %d", intf_ptr->bInterfaceClass);
            printf("  SubClass = %d", intf_ptr->bInterfaceSubClass);
            printf("  Protocol = %d\n", intf_ptr->bInterfaceProtocol);
            //fflush(stdout);
            status = usb_host_close_dev_interface(host_handle, g_kbd_hid_device.dev_handle, g_kbd_hid_device.intf_handle,  g_kbd_hid_device.class_handle);
            if (status != USB_OK)
            {
                printf("error in _usb_hostdev_close_interface %x\n", status);
            }
            g_kbd_hid_device.dev_handle = NULL;
            g_kbd_hid_device.intf_handle = NULL;
			g_kbd_hid_device.dev_state = USB_DEVICE_IDLE;
            OS_Event_set(usb_keyboard_event, USB_Keyboard_Event_CTRL);
            break;
    }
   
}
Ejemplo n.º 4
0
void APP_init(void)
{
    usb_status status = USB_OK;
    uint32_t opt = 0;

    status = usb_host_init(CONTROLLER_ID, usb_host_board_init, &g_host_handle);
    if (status != USB_OK)
    {
        USB_PRINTF("\r\nUSB Host Initialization failed! STATUS: 0x%x", status);
        return;
    }
    /*
     ** since we are going to act as the host driver, register the driver
     ** information for wanted class/subclass/protocols
     */
    status = usb_host_register_driver_info(g_host_handle, (void *) DriverInfoTable);
    if (status != USB_OK)
    {
        USB_PRINTF("\r\nUSB Initialization driver info failed! STATUS: 0x%x", status);
        return;
    }

    status = usb_host_register_unsupported_device_notify(g_host_handle, usb_host_hid_unsupported_device_event);
    if (status != USB_OK)
    {
        USB_PRINTF("\r\nUSB Initialization driver info failed! STATUS: 0x%x", status);
        return;
    }

    mouse_usb_event = OS_Event_create(0);/* manually clear */
    if (mouse_usb_event == NULL)
    {
        USB_PRINTF("mouse_usb_event create failed\r\n");
        return;
    }
    mouse_hid_com = (hid_command_t*) OS_Mem_alloc_zero(sizeof(hid_command_t));
    if (mouse_hid_com == NULL)
    {
        USB_PRINTF("mouse_hid_com create failed\r\n");
        return;
    }

    kbd_usb_event = OS_Event_create(0);/* manually clear */
    if (kbd_usb_event == NULL)
    {
        USB_PRINTF("kbd_usb_event create failed\r\n");
        return;
    }
    OS_Event_set(kbd_usb_event, USB_EVEN_INIT);
    kbd_hid_com = (hid_command_t*) OS_Mem_alloc_zero(sizeof(hid_command_t));
    if (kbd_hid_com == NULL)
    {
        USB_PRINTF("kbd_hid_com create failed\r\n");
        return;
    }

    if ((uint32_t) OS_TASK_ERROR == OS_Task_create(USB_KEYBOARD_TASK_ADDRESS, (void*) g_host_handle, (uint32_t) USB_KEYBOARD_TASK_PRIORITY, USB_KEYBOARD_TASK_STACKSIZE, USB_KEYBOARD_TASK_NAME, &opt))
    {
        USB_PRINTF("keyboard task create failed\r\n");
        return;
    }

    if ((uint32_t) OS_TASK_ERROR == OS_Task_create(USB_MOUSE_TASK_ADDRESS, (void*) g_host_handle, (uint32_t) USB_MOUSE_TASK_PRIORITY, USB_MOUSE_TASK_STACKSIZE, USB_MOUSE_TASK_NAME, &opt))
    {
        USB_PRINTF("mouse task create failed\r\n");
        return;
    }
    time_init();
    USB_PRINTF("\fUSB HID Mouse+Keyboard\r\nWaiting for USB Mouse or Keyboard to be attached...\r\n");
}
Ejemplo n.º 5
0
/* 
    usb_host_video_stream_event
*/
void usb_host_video_stream_event
(
    /* [IN] pointer to device instance */
    usb_device_instance_handle dev_handle,
    /* [IN] pointer to interface descriptor */
    usb_interface_descriptor_handle intf_handle,
    /* [IN] code number for event causing callback */
    uint32_t event_code
)
{
    usb_device_interface_struct_t* pHostIntf = (usb_device_interface_struct_t*)intf_handle;
    interface_descriptor_t* intf_ptr = pHostIntf->lpinterfaceDesc;

    switch (event_code)
    {
    case USB_ATTACH_EVENT:
        g_video_camera.interface_ptr[g_video_camera.interface_number] = pHostIntf;
        g_video_camera.interface_type[g_video_camera.interface_number] = USB_SUBCLASS_VIDEO_STREAMING;
        g_video_camera.interface_number++;
        USB_PRINTF("----- Attach Event -----\r\n");
        USB_PRINTF("State = %d", g_video_camera.stream_state);
        USB_PRINTF("  Interface Number = %d", intf_ptr->bInterfaceNumber);
        USB_PRINTF("  Alternate Setting = %d", intf_ptr->bAlternateSetting);
        USB_PRINTF("  Class = %d", intf_ptr->bInterfaceClass);
        USB_PRINTF("  SubClass = %d", intf_ptr->bInterfaceSubClass);
        USB_PRINTF("  Protocol = %d\r\n", intf_ptr->bInterfaceProtocol);
        break;
    case USB_CONFIG_EVENT:
        if(g_video_camera.stream_state == USB_DEVICE_IDLE)
        {
            if ((NULL != g_video_camera.dev_handle) && (g_video_camera.dev_handle != dev_handle))
            {
                USB_PRINTF("Video device already attached - Control DEV_STATE = %d\r\n", g_video_camera.control_state);
                USB_PRINTF("Video device already attached - Stream DEV_STATE = %d\r\n", g_video_camera.stream_state);
                return;
            }
            g_video_camera.dev_handle = dev_handle;
            for(int i = 0;i < g_video_camera.interface_number;i++)
            {
                if(g_video_camera.interface_type[i] == USB_SUBCLASS_VIDEO_STREAMING)
                {
                    g_video_camera.stream_intf_handle = g_video_camera.interface_ptr[i];
                    break;
                }
            }
            g_video_camera.stream_state = USB_DEVICE_ATTACHED;
        }
        else
        {
             USB_PRINTF("Video device already attached - Stream DEV_STATE = %d\r\n", g_video_camera.stream_state);
        }
        break;

    case USB_INTF_OPENED_EVENT:
        USB_PRINTF("----- Interfaced Event -----\r\n");
        g_video_camera.stream_state = USB_DEVICE_INTERFACE_OPENED;
        break;

    case USB_DETACH_EVENT:
        /* Use only the interface with desired protocol */
        USB_PRINTF("\r\n----- Detach Event -----\r\n");
        USB_PRINTF("State = %d", g_video_camera.stream_state);
        USB_PRINTF("  Interface Number = %d", intf_ptr->bInterfaceNumber);
        USB_PRINTF("  Alternate Setting = %d", intf_ptr->bAlternateSetting);
        USB_PRINTF("  Class = %d", intf_ptr->bInterfaceClass);
        USB_PRINTF("  SubClass = %d", intf_ptr->bInterfaceSubClass);
        USB_PRINTF("  Protocol = %d\r\n", intf_ptr->bInterfaceProtocol);
        g_video_camera.interface_number --;
        g_video_camera.stream_state = USB_DEVICE_DETACHED;
        break;
        
    default:
        USB_PRINTF("Video Device state = %d??\r\n", g_video_camera.stream_state);
        g_video_camera.stream_state = USB_DEVICE_IDLE;
        break;
    }

    /* notify application that status has changed */
    OS_Event_set(g_video_camera.video_camera_stream_event, USB_EVENT_CTRL);
}
Ejemplo n.º 6
0
/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    : _usb_otg_sm_b
* Returned Value   :
* Comments         : This function handles the substates of the B-state machine
*    
*
*END*----------------------------------------------------------------------*/
void _usb_otg_sm_b
(
    usb_otg_handle otg_handle
)
{
    usb_otg_state_struct_t * usb_otg_struct_ptr = (usb_otg_state_struct_t *)otg_handle;
    usb_otg_status_t           *otg_status        =  &usb_otg_struct_ptr->otg_status;

    if (!otg_status->id)
    {  
        _usb_otg_id_chg_a(otg_handle);
        return;
    }

    switch (usb_otg_struct_ptr->sub_state)
    {
    case USB_OTG_SM_B_IDLE_SESS_DETECT:
        usb_otg_struct_ptr->hnp_enabled = FALSE;
        if (otg_status->sess_valid)
        {
            _usb_otg_sm_b_substate_change(otg_handle, USB_OTG_SM_B_PERI_BUS_SUSP_DETECT, OTG_B_PERIPHERAL);                 
        }
        else
        {
            /* Disable pull-up. The B-Device is now in the B-Idle state */
            _usb_otg_callback_set_dp_pull_up(otg_handle, FALSE);
            if (otg_status->sess_end)
            {              
                usb_otg_struct_ptr->sub_state = USB_OTG_SM_B_IDLE_SESS_END_DETECT;
                
                otg_status->b_timeout = TB_SESSEND_SRP; /* Program the SRP detect timeout as SESSEND SRP */
            }
        }
        break;
    case USB_OTG_SM_B_IDLE_SESS_END_DETECT:
        if (otg_status->sess_valid)
        {
            _usb_otg_sm_b_substate_change(otg_handle, USB_OTG_SM_B_PERI_BUS_SUSP_DETECT, OTG_B_PERIPHERAL);
        }
        else
        {              
            /* Read the Live SE0 bit */
            if ((otg_status->live_se0) && (otg_status->line_stable))
            {                                
                otg_status->b_timeout_en = TRUE;
                
                usb_otg_struct_ptr->sub_state = USB_OTG_SM_B_IDLE_SE0_STABLE_WAIT;
            }            
        }
        break;
    case USB_OTG_SM_B_IDLE_SE0_STABLE_WAIT:
        if (otg_status->sess_valid)
        {
            _usb_otg_sm_b_substate_change(otg_handle, USB_OTG_SM_B_PERI_BUS_SUSP_DETECT, OTG_B_PERIPHERAL);
        }
        else
        {
            /* Line state change. restart SE0 detection */
            if (!otg_status->line_stable)
            {               
                otg_status->b_timeout_en = TRUE;
                
                otg_status->b_timeout = TB_SE0_SRP; /* reinitialize the the SE0 detect timer */
                
                /* Keep the current state */
            }
            else
            {
                if (otg_status->b_timeout == 0)
                {
                    /* The timeout expired during stable SE0 */
                    _usb_otg_sm_b_substate_change(otg_handle, USB_OTG_SM_B_IDLE_SRP_START_ARMED, OTG_B_IDLE_SRP_READY);               
                }
            }
        }
        break; 
        
    case USB_OTG_SM_B_IDLE_SRP_START_ARMED:
        if (otg_status->sess_valid)
        {
            _usb_otg_sm_b_substate_change(otg_handle, USB_OTG_SM_B_PERI_BUS_SUSP_DETECT, OTG_B_PERIPHERAL);
        }
        else
        {                
            /* Line state change. restart SE0 detection */
            if (!otg_status->line_stable)
            {
                otg_status->b_timeout = TB_SE0_SRP; /* reinitialize the the SE0 detect timer */              
                usb_otg_struct_ptr->sub_state = USB_OTG_SM_B_IDLE_SESS_END_DETECT;
            }
            else
            {
                if (usb_otg_struct_ptr->srp_request || usb_otg_struct_ptr->power_up)
                {
                    usb_otg_struct_ptr->power_up = FALSE;
                    usb_otg_struct_ptr->srp_request = FALSE;
                    /* Start SRP */                                  
                    /* Start the D+ pulsing timeout */              
                    otg_status->b_timeout = TB_DATA_PLS; /* reinitialize the the SE0 detect timer */                 
                    otg_status->b_timeout_en = TRUE;
                    /* Enable D+ pullup */
                    _usb_otg_callback_set_dp_pull_up(otg_handle, TRUE);
                    usb_otg_struct_ptr->sub_state = USB_OTG_SM_B_SRP_PULSE;                                                   
                }
            }
        }
        break;
    case USB_OTG_SM_B_SRP_PULSE:
        if (otg_status->b_timeout == 0)
        {
            /* The timeout expired. Remove the D+ pullup */
            _usb_otg_callback_set_dp_pull_up(otg_handle, FALSE);
            /* Wait for VBUS */
            otg_status->b_timeout = (TB_SRP_FAIL - TB_DATA_PLS);
            otg_status->b_timeout_en = TRUE;
            
            usb_otg_struct_ptr->sub_state = USB_OTG_SM_B_SRP_VBUS_WAIT;
            
            /* Signal the event to the application */
            OS_Event_set((usb_otg_struct_ptr->otg_app_event), OTG_B_SRP_INIT);               
        }
        break;
        
    case USB_OTG_SM_B_SRP_VBUS_WAIT:
        if (otg_status->sess_valid)
        {
            _usb_otg_sm_b_substate_change(otg_handle, USB_OTG_SM_B_PERI_BUS_SUSP_DETECT, OTG_B_PERIPHERAL);
        }
        else
        {
            if (otg_status->b_timeout == 0)
            {
                /* The timeout expired during VBUS wait */               
                
                /* Inform the application about the failed SRP and return to idle state */               
                /* and wait for SE0 condition on the bus to be able to restart the SRP */
                
                usb_otg_struct_ptr->sub_state = USB_OTG_SM_B_IDLE_SE0_STABLE_WAIT;
                
                otg_status->b_timeout_en = TRUE;
                
                otg_status->b_timeout = TB_SE0_SRP; /* reinitialize the the SE0 detect timer */
                
                /* Signal the event to the application */
                OS_Event_set((usb_otg_struct_ptr->otg_app_event), OTG_B_SRP_FAIL);
            }
        }
        break;
    case USB_OTG_SM_B_PERI_BUS_SUSP_DETECT:
        if (!otg_status->sess_valid)
        {
            _usb_otg_sm_b_substate_change(otg_handle, USB_OTG_SM_B_IDLE_SESS_DETECT, OTG_B_IDLE); 
        }
        else
        {
            /* Enable the D+ pull-up. the B device is in the peripheral state */
            _usb_otg_callback_set_dp_pull_up(otg_handle, TRUE);
            usb_otg_struct_ptr->power_up = FALSE;

            /* Start monitoring the data lines. 
            * If the bus has inactivity for more than TB_AIDL_BDIS, then the A is considered disconnected and B can start HNP
            */ 
            usb_otg_struct_ptr->sub_state = USB_OTG_SM_B_PERI_BUS_SUSP_WAIT;
            otg_status->b_timeout_en = TRUE;
            otg_status->b_timeout = TB_AIDL_BDIS; /* reinitialize the IDLE detect timer */             
        }
        break;
    case USB_OTG_SM_B_PERI_BUS_SUSP_WAIT:
        if (!otg_status->sess_valid)
        {
            _usb_otg_sm_b_substate_change(otg_handle, USB_OTG_SM_B_IDLE_SESS_DETECT, OTG_B_IDLE); 
        }
        else
        {
            if (!otg_status->line_stable)
            {              
                /* Restart detection */
                otg_status->b_timeout_en = TRUE;
                otg_status->b_timeout = TB_AIDL_BDIS; /* reinitialize the IDLE detect timer */
            }
            else
            {
                if ((usb_otg_struct_ptr->hnp_enabled) && (otg_status->b_timeout == 0))
                {
                    usb_otg_struct_ptr->sub_state = USB_OTG_SM_B_PERI_HNP_ARMED;    
                    /* Signal the event to the application */
                    OS_Event_set((usb_otg_struct_ptr->otg_app_event), OTG_B_PERIPHERAL_HNP_READY); 
                }
            }
        }
        break;
    case USB_OTG_SM_B_PERI_HNP_ARMED:
        if (!otg_status->sess_valid)
        {
            _usb_otg_sm_b_substate_change(otg_handle, USB_OTG_SM_B_IDLE_SESS_DETECT, OTG_B_IDLE); 
        }
        else
        {              
            if ((!otg_status->line_stable) || (!usb_otg_struct_ptr->hnp_enabled))
            {
                _usb_otg_sm_b_substate_change(otg_handle, USB_OTG_SM_B_PERI_BUS_SUSP_DETECT, OTG_B_PERIPHERAL_HNP_FAIL);
            }
            else
            {
                if ((usb_otg_struct_ptr->bus_request) && (usb_otg_struct_ptr->hnp_enabled))
                {
                    usb_otg_struct_ptr->bus_request = FALSE;
                    
                    /* Clear the Status at the USB device level */
                    _usb_device_set_status(usb_otg_struct_ptr->dev_inst_ptr, USB_STATUS_OTG, USB_STATUS_IDLE);
                    /* Start HNP. Turn off Pull-Up on D+ for the Host to detect SE0 */
                    _usb_otg_callback_set_dp_pull_up(otg_handle, FALSE);
                    /* Wait for data line to discharge (25us) */
                    otg_status->b_timeout = 1;
                    otg_status->b_timeout_en = TRUE;
                    usb_otg_struct_ptr->sub_state = USB_OTG_SM_B_PERI_HNP_START;
                    /* Signal the event to the application */
                    OS_Event_set ((usb_otg_struct_ptr->otg_app_event), OTG_B_PERIPHERAL_HNP_START);                    
                }
            }
        }
        break;
    case USB_OTG_SM_B_PERI_HNP_START:
        if (!otg_status->sess_valid)
        {
            _usb_otg_sm_b_substate_change(otg_handle, USB_OTG_SM_B_IDLE_SESS_DETECT, OTG_B_IDLE); 
        }
        else
        {
            if (otg_status->b_timeout == 0)
            {
                /* Line should have discharged by now */
                /* Start the host disconnect detect */
                otg_status->b_timeout = TB_ASE0_BRST;
                otg_status->b_timeout_en = TRUE;              
                usb_otg_struct_ptr->sub_state = USB_OTG_SM_B_PERI_HNP_ACONN;    
            }
        }
        break;
    case USB_OTG_SM_B_PERI_HNP_ACONN: 
        if (!otg_status->sess_valid)
        {
            _usb_otg_sm_b_substate_change(otg_handle, USB_OTG_SM_B_IDLE_SESS_DETECT, OTG_B_IDLE); 
        }
        else
        {
            if (otg_status->b_timeout == 0)
            {
                /* A connect timeout detected. Go back to peripheral state */
                _usb_otg_sm_b_substate_change(otg_handle, USB_OTG_SM_B_PERI_BUS_SUSP_DETECT, OTG_B_PERIPHERAL_HNP_FAIL);
            }
            else
            {
                /* Check the Data line state */
                if ((!otg_status->live_se0) && (otg_status->live_jstate) && (otg_status->line_stable))
                {
                    /* J-STATE. Host has been released */
                    /* Enter the B-Host state */
                    usb_otg_struct_ptr->hnp_enabled = FALSE;
                    otg_status->a_conn = TRUE;
                    _usb_otg_sm_b_substate_change(otg_handle, USB_OTG_SM_B_HOST, OTG_B_HOST);
                }
                else
                {
                    if ((!otg_status->live_se0) && (!otg_status->live_jstate) && (otg_status->line_stable))
                    {
                        /* Host has retained the bus */
                        _usb_otg_sm_b_substate_change(otg_handle, USB_OTG_SM_B_PERI_BUS_SUSP_DETECT, OTG_B_PERIPHERAL_HNP_FAIL);               
                    }
                }
            }
        }
        break;
    case USB_OTG_SM_B_HOST:
        if (!otg_status->sess_valid)
        {
            otg_status->a_conn = FALSE;
            _usb_otg_sm_b_substate_change(otg_handle, USB_OTG_SM_B_IDLE_SESS_DETECT, OTG_B_IDLE); 
        }
        else
        {
            if ((otg_status->a_conn == FALSE) || usb_otg_struct_ptr->bus_release)
            {
                usb_otg_struct_ptr->bus_release = FALSE;
                otg_status->a_conn = FALSE;
                /* A-device disconnected or B has finished using the bus */
                _usb_otg_sm_b_substate_change(otg_handle, USB_OTG_SM_B_PERI_BUS_SUSP_DETECT, OTG_B_PERIPHERAL);
            } 
            else 
            {
                if ( usb_otg_struct_ptr->dev_inst_ptr != NULL )
                {
                    if (otg_status->hnp_req)
                    {
                        OS_Event_set((usb_otg_struct_ptr->otg_app_event), OTG_B_A_HNP_REQ);
                    }
                    if (otg_status->hnp_support && (otg_status->host_req_poll_timer >= T_HOST_REQ_POLL))
                    {
                        otg_status->host_req_poll_timer = 0;
                        _usb_otg_hnp_poll_req(usb_otg_struct_ptr);  
                    } 
                }
            }
        }
        break;
    default: break;
    }  
}