/** * @brief USBH_Init * Host hardware and stack initializations * @param class_cb: Class callback structure address * @param usr_cb: User callback structure address * @retval None */ void USBH_Init(USB_OTG_CORE_HANDLE *pdev, USB_OTG_CORE_ID_TypeDef coreID, USBH_HOST *phost, USBH_Class_cb_TypeDef *class_cb, USBH_Usr_cb_TypeDef *usr_cb) { /* Hardware Init */ USB_OTG_BSP_Init(pdev); /* configure GPIO pin used for switching VBUS power */ USB_OTG_BSP_ConfigVBUS(0); /* Host de-initializations */ USBH_DeInit(pdev, phost); /*Register class and user callbacks */ phost->class_cb = class_cb; phost->usr_cb = usr_cb; /* Start the USB OTG core */ HCD_Init(pdev , coreID); /* Upon Init call usr call back */ phost->usr_cb->Init(); /* Enable Interrupts */ USB_OTG_BSP_EnableInterrupt(pdev); }
/** * This function will initialize susb host controller device. * * @param dev the host controller device to be initalize. * * @return the error code, RT_EOK on successfully. */ static rt_err_t susb_init(rt_device_t dev) { rt_sem_init(&sem_lock, "s_lock", 1, RT_IPC_FLAG_FIFO); /* roothub initilizition */ root_hub.num_ports = 1; root_hub.is_roothub = RT_TRUE; root_hub.self = RT_NULL; root_hub.hcd = &susb_hcd; /* Hardware Init */ USB_OTG_BSP_Init(&USB_OTG_Core); /* configure GPIO pin used for switching VBUS power */ USB_OTG_BSP_ConfigVBUS(0); /* Host de-initializations */ USBH_DeInit(&USB_OTG_Core, &USB_Host); /* Start the USB OTG core */ HCD_Init(&USB_OTG_Core , USB_OTG_FS_CORE_ID); USBH_DeAllocate_AllChannel(&USB_OTG_Core); /* Enable Interrupts */ USB_OTG_BSP_EnableInterrupt(&USB_OTG_Core); return RT_EOK; }
/** * @brief USBH_Process * USB Host core main state machine process * @param None * @retval None */ void USBH_Process(USB_OTG_CORE_HANDLE *pdev, USBH_HOST *phost) { volatile USBH_Status status = USBH_FAIL; // if (USB_DEBUG) { // USB_debugEvent(); // xprintf("USBH_Process phost->gState = %d\n", phost->gState); // } /* check for Host port events */ if (((HCD_IsDeviceConnected(pdev) == 0) || (HCD_IsPortEnabled(pdev) == 0)) && (phost->gState != HOST_IDLE)) { if (phost->gState != HOST_DEV_DISCONNECTED) { phost->gState = HOST_DEV_DISCONNECTED; // if (USB_DEBUG){ // USB_debugEvent(); // } } } switch (phost->gState) { case HOST_IDLE: if (HCD_IsDeviceConnected(pdev)) { phost->gState = HOST_WAIT_PRT_ENABLED; /*wait debounce delay */ USB_OTG_BSP_mDelay(200); // was 100 // if (USB_DEBUG){ // USB_debugEvent(); // } /* Apply a port RESET */ HCD_ResetPort(pdev); /* User RESET callback*/ phost->usr_cb->ResetDevice(); } break; case HOST_WAIT_PRT_ENABLED: if (pdev->host.PortEnabled == 1) { phost->gState = HOST_DEV_ATTACHED; } break; case HOST_DEV_ATTACHED: phost->usr_cb->DeviceAttached(); phost->Control.hc_num_out = USBH_Alloc_Channel(pdev, 0x00); phost->Control.hc_num_in = USBH_Alloc_Channel(pdev, 0x80); // if (USB_DEBUG){ // USB_debugEvent(); // } phost->device_prop.speed = HCD_GetCurrentSpeed(pdev); phost->gState = HOST_ENUMERATION; phost->usr_cb->DeviceSpeedDetected(phost->device_prop.speed); // if (USB_DEBUG){ // USB_debugEvent(); // } /* Open Control pipes */ USBH_Open_Channel(pdev, phost->Control.hc_num_in, phost->device_prop.address, phost->device_prop.speed, EP_TYPE_CTRL, phost->Control.ep0size); // if (USB_DEBUG){ // USB_debugEvent(); // } /* Open Control pipes */ USBH_Open_Channel(pdev, phost->Control.hc_num_out, phost->device_prop.address, phost->device_prop.speed, EP_TYPE_CTRL, phost->Control.ep0size); // if (USB_DEBUG){ // USB_debugEvent(); // } break; case HOST_ENUMERATION: /* Check for enumeration status */ if (USBH_HandleEnum(pdev, phost) == USBH_OK) { /* The function shall return USBH_OK when full enumeration is complete */ /* user callback for end of device basic enumeration */ phost->usr_cb->EnumerationDone(); phost->gState = HOST_USR_INPUT; // if (USB_DEBUG){ // USB_debugEvent(); // } } break; case HOST_USR_INPUT: /*The function should return user response true to move to class state */ if (phost->usr_cb->UserInput() == USBH_USR_RESP_OK) { if ((phost->class_cb->Init(pdev, phost))\ == USBH_OK) { phost->gState = HOST_CLASS_REQUEST; } // if (USB_DEBUG){ // USB_debugEvent(); // } } break; case HOST_CLASS_REQUEST: /* process class standard contol requests state machine */ // if (USB_DEBUG){ // USB_debugEvent(); // } status = phost->class_cb->Requests(pdev, phost); if (status == USBH_OK) { phost->gState = HOST_CLASS; // if (USB_DEBUG){ // USB_debugEvent(); // } } else { // if (USB_DEBUG){ // USB_debugEvent(); // } USBH_ErrorHandle(phost, status); } break; case HOST_CLASS: /* process class state machine */ status = phost->class_cb->Machine(pdev, phost); // if (USB_DEBUG){ // USB_debugEvent(); // } USBH_ErrorHandle(phost, status); break; case HOST_CTRL_XFER: /* process control transfer state machine */ // if (USB_DEBUG){ // USB_debugEvent(); // } USBH_HandleControl(pdev, phost); break; case HOST_SUSPENDED: break; case HOST_ERROR_STATE: /* Re-Initilaize Host for new Enumeration */ // if (USB_DEBUG){ // USB_debugEvent(); // } USBH_DeInit(pdev, phost); phost->usr_cb->DeInit(); phost->class_cb->DeInit(pdev, &phost->device_prop); break; case HOST_DEV_DISCONNECTED: // if (USB_DEBUG){ // USB_debugEvent(); // } /* Manage User disconnect operations*/ phost->usr_cb->DeviceDisconnected(); /* Re-Initilaize Host for new Enumeration */ USBH_DeInit(pdev, phost); phost->usr_cb->DeInit(); phost->class_cb->DeInit(pdev, &phost->device_prop); USBH_DeAllocate_AllChannel(pdev); phost->gState = HOST_IDLE; /* Re-Initilaize Host for new Enumeration */ HCD_Init(pdev, #ifdef USE_USB_OTG_FS USB_OTG_FS_CORE_ID #else USB_OTG_HS_CORE_ID #endif ); break; default: break; } }
/** * @brief USBH_Process * USB Host core main state machine process * @param None * @retval None */ void USBH_Process(USB_OTG_CORE_HANDLE *pdev , USBH_HOST *phost) { volatile USBH_Status status = USBH_FAIL; /* check for Host port events */ if (((HCD_IsDeviceConnected(pdev) == 0)|| (HCD_IsPortEnabled(pdev) == 0))&& (phost->gState != HOST_IDLE)) { if(phost->gState != HOST_DEV_DISCONNECTED) { phost->gState = HOST_DEV_DISCONNECTED; } } switch (phost->gState) { case HOST_IDLE : if (HCD_IsDeviceConnected(pdev)) { phost->gState = HOST_WAIT_PRT_ENABLED; /*wait denounce delay */ USB_OTG_BSP_mDelay(100); /* Apply a port RESET */ HCD_ResetPort(pdev); /* User RESET callback*/ phost->usr_cb->ResetDevice(); } break; case HOST_WAIT_PRT_ENABLED: if (pdev->host.PortEnabled == 1) { phost->gState = HOST_DEV_ATTACHED; USB_OTG_BSP_mDelay(50); } break; case HOST_DEV_ATTACHED : phost->usr_cb->DeviceAttached(); phost->Control.hc_num_out = USBH_Alloc_Channel(pdev, 0x00); phost->Control.hc_num_in = USBH_Alloc_Channel(pdev, 0x80); /* Reset USB Device */ if ( HCD_ResetPort(pdev) == 0) { phost->usr_cb->ResetDevice(); /* Host is Now ready to start the Enumeration */ phost->device_prop.speed = HCD_GetCurrentSpeed(pdev); phost->gState = HOST_ENUMERATION; phost->usr_cb->DeviceSpeedDetected(phost->device_prop.speed); /* Open Control pipes */ USBH_Open_Channel (pdev, phost->Control.hc_num_in, phost->device_prop.address, phost->device_prop.speed, EP_TYPE_CTRL, phost->Control.ep0size); /* Open Control pipes */ USBH_Open_Channel (pdev, phost->Control.hc_num_out, phost->device_prop.address, phost->device_prop.speed, EP_TYPE_CTRL, phost->Control.ep0size); } break; case HOST_ENUMERATION: /* Check for enumeration status */ if ( USBH_HandleEnum(pdev , phost) == USBH_OK) { /* The function shall return USBH_OK when full enumeration is complete */ /* user callback for end of device basic enumeration */ phost->usr_cb->EnumerationDone(); #if defined (USB_OTG_FS_LOW_PWR_MGMT_SUPPORT) || defined (USB_OTG_HS_LOW_PWR_MGMT_SUPPORT) phost->gState = HOST_SUSPENDED; #else phost->gState = HOST_USR_INPUT; #endif /* LOW_PWR_MGMT_SUPPORT*/ } break; case HOST_USR_INPUT: /*The function should return user response true to move to class state */ if ( phost->usr_cb->UserInput() == USBH_USR_RESP_OK) { if((phost->class_cb->Init(pdev, phost))\ == USBH_OK) { phost->gState = HOST_CLASS_REQUEST; } } break; case HOST_CLASS_REQUEST: /* process class standard control requests state machine */ status = phost->class_cb->Requests(pdev, phost); if(status == USBH_OK) { phost->gState = HOST_CLASS; } else { USBH_ErrorHandle(phost, status); } break; case HOST_CLASS: /* process class state machine */ status = phost->class_cb->Machine(pdev, phost); USBH_ErrorHandle(phost, status); break; case HOST_CTRL_XFER: /* process control transfer state machine */ USBH_HandleControl(pdev, phost); break; #if defined (USB_OTG_FS_LOW_PWR_MGMT_SUPPORT) || defined (USB_OTG_HS_LOW_PWR_MGMT_SUPPORT) case HOST_SUSPENDED: if (USBH_SetDeviceFeature(pdev, phost, FEATURE_SELECTOR_DEVICE, 0)==USBH_OK) { suspend_flag = 1; USB_OTG_BSP_Suspend(pdev); phost->usr_cb->UserInput(); PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI); /* After wakeup got to HOST_WAKEUP state */ phost->gState = HOST_WAKEUP; } break; case HOST_WAKEUP: /* issue a ClearDeviceFeature request */ if (USBH_ClearDeviceFeature(pdev, phost, FEATURE_SELECTOR_DEVICE, 0)==USBH_OK) { phost->gState = HOST_USR_INPUT; } break; #endif /* USE_HOST_MODE */ case HOST_ERROR_STATE: /* Re-Initialize Host for new Enumeration */ USBH_DeInit(pdev, phost); phost->usr_cb->DeInit(); phost->class_cb->DeInit(pdev, &phost->device_prop); break; case HOST_DEV_DISCONNECTED : /* Manage User disconnect operations*/ phost->usr_cb->DeviceDisconnected(); /* Re-Initialize Host for new Enumeration */ USBH_DeInit(pdev, phost); phost->usr_cb->DeInit(); phost->class_cb->DeInit(pdev, &phost->device_prop); USBH_DeAllocate_AllChannel(pdev); phost->gState = HOST_IDLE; /* Re-Initialize Host for new Enumeration */ HCD_Init(pdev, #ifdef USE_USB_OTG_FS USB_OTG_FS_CORE_ID #else USB_OTG_HS_CORE_ID #endif ); break; default : break; } }