/** * @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)&& (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_DEV_ATTACHED; USB_OTG_BSP_mDelay(100); } 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(); /* Wait for USB USBH_ISR_PrtEnDisableChange() 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(); phost->gState = HOST_USR_INPUT; } 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 contol 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; case HOST_SUSPENDED: break; case HOST_ERROR_STATE: /* Re-Initilaize 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-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; 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; // 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; } }
void USBH_Dev_HID_EnumerationDone(USB_OTG_CORE_HANDLE *pcore, USBH_DEV *pdev) { if (pdev->Usr_Data != 0) { free(pdev->Usr_Data); pdev->Usr_Data = 0; } uint8_t numIntf = pdev->device_prop.Cfg_Desc.bNumInterfaces; char isHid = 0; pdev->Usr_Data = calloc(1, sizeof(HID_Data_t)); HID_Data_t* HID_Data = pdev->Usr_Data; HID_Data->io = calloc(numIntf, sizeof(USBH_DevIO_t*)); HID_Data->ioIdx = 0; dbg_printf(DBGMODE_DEBUG, "USBH_Dev_HID_EnumerationDone, bNumInterfaces: %d\r\n", numIntf); for (int i = 0; i < numIntf; i++) { // filter out non-HID class interfaces if (pdev->device_prop.Itf_Desc[i].bInterfaceClass != 0x03) { continue; } isHid = 1; USBH_DevD2H_DataHandler_t dataHandler = 0; HID_Rpt_Parsing_Params_t* parser = 0; uint8_t parserEp = 0; if (pdev->device_prop.Dev_Desc.idVendor == SONY_VID && pdev->device_prop.Dev_Desc.idProduct == DUALSHOCK3_PID) { // DUALSHOCK3 dataHandler = USBH_DS3_Data_Handler; dbg_printf(DBGMODE_TRACE, "Dualshock 3 Detected\r\n"); } else if (pdev->device_prop.Dev_Desc.idVendor == SONY_VID && pdev->device_prop.Dev_Desc.idProduct == DUALSHOCK4_PID) { // DUALSHOCK4 dataHandler = USBH_DS4_Data_Handler; HID_Data->init_handler = USBH_DS4_Init_Handler; HID_Data->deinit_handler = USBH_DS4_DeInit_Handler; HID_Data->custom_task = USBH_DS4_Task; dbg_printf(DBGMODE_TRACE, "Dualshock 4 Detected\r\n"); } // TODO handle others, like Xbox controllers else { // other, probably keyboard or mouse parser = malloc(sizeof(HID_Rpt_Parsing_Params_t)); dataHandler = HID_Default_Data_Handler; } uint8_t maxEP = ( (pdev->device_prop.Itf_Desc[i].bNumEndpoints <= USBH_MAX_NUM_ENDPOINTS) ? pdev->device_prop.Itf_Desc[i].bNumEndpoints : USBH_MAX_NUM_ENDPOINTS); // assign interrupt endpoints to channels, and polling parameters for the D2H endpoint // warning: assume 1 interrupt endpoint per direction for (int j = 0; j < maxEP; j++) { USBH_EpDesc_TypeDef* epDesc = &(pdev->device_prop.Ep_Desc[i][j]); if ((epDesc->bmAttributes & EP_TYPE_MSK) == USB_EP_TYPE_INTR) { if ((epDesc->bEndpointAddress & USB_EP_DIR_MSK) == USB_EP_DIR_IN) { HID_Data->io[i] = USBH_DevIO_Manager_New(pcore, pdev, epDesc, #ifdef USBH_HID_ENABLE_DYNAMIC_HC_ALLOC 1 #else 0 #endif , dataHandler, parser ); parserEp = epDesc->bEndpointAddress; } } } USBH_Status status; if (parser != 0) { USBH_HIDDesc_TypeDef hidDesc; status = USBH_Get_HID_Descriptor_Blocking (pcore, pdev, i); if (status == USBH_OK) { USBH_ParseHIDDesc(&hidDesc, pcore->host.Rx_Buffer); vcp_printf("%sI%d:C%d:HIDDesc:\r\n", USBH_Dev_DebugPrint(pdev, 0), i, USB_HID_DESC_SIZE); for (uint8_t k = 0; k < USB_HID_DESC_SIZE; k++) { vcp_printf(" 0x%02X", pcore->host.Rx_Buffer[k]); } vcp_printf("\r\n"); } else { dbg_printf(DBGMODE_ERR, "USBH_Get_HID_Descriptor_Blocking failed status: 0x%04X\r\n", status); USBH_ErrorHandle(pcore, pdev, status); continue; } uint8_t repIdList[8] = { 0, 0, 0, 0, 0, 0, 0, 0}; status = USBH_Get_HID_ReportDescriptor_Blocking(pcore , pdev, i, hidDesc.wItemLength); if (status == USBH_OK) { dbg_printf(DBGMODE_DEBUG, "USBH_Get_HID_ReportDescriptor_Blocking OK: 0x%04X\r\n", status); vcp_printf("%sI%d:C%d:ReptDesc:", USBH_Dev_DebugPrint(pdev, 0), i, hidDesc.wItemLength); for (uint8_t k = 0; k < hidDesc.wItemLength; k++) { vcp_printf(" 0x%02X", pcore->host.Rx_Buffer[k]); } vcp_printf("\r\n"); HID_Rpt_Parsing_Params_Reset(parser); HID_Rpt_Desc_Parse(pcore->host.Rx_Buffer, hidDesc.wItemLength, parser, parserEp, repIdList); //dbg_printf(DBGMODE_DEBUG, "HID_Rpt_Desc_Parse Complete \r\n"); HID_Rpt_Parsing_Params_Debug_Dump(parser); } else { dbg_printf(DBGMODE_ERR, "USBH_Get_HID_ReportDescriptor_Blocking failed status: 0x%04X\r\n", status); USBH_ErrorHandle(pcore, pdev, status); continue; } char hasSetIdle = 0; for (int ridIdx = 0; ridIdx < 8; ridIdx++) { uint8_t rid = repIdList[ridIdx]; if (rid > 0) { hasSetIdle = 1; status = USBH_Set_Idle_Blocking (pcore, pdev, i, 0, rid); if (status == USBH_OK) { dbg_printf(DBGMODE_DEBUG, "USBH_Set_Idle_Blocking[%d] OK: 0x%04X\r\n", rid, status); } else if(status == USBH_NOT_SUPPORTED || status == USBH_STALL) { dbg_printf(DBGMODE_DEBUG, "USBH_Set_Idle_Blocking[%d] NOT SUPPORTED\r\n", rid); } else { dbg_printf(DBGMODE_ERR, "USBH_Set_Idle_Blocking[%d] failed status: 0x%04X\r\n", rid, status); USBH_ErrorHandle(pcore, pdev, status); } } // end of list if (rid == 0) { break; } } if (hasSetIdle == 0) { status = USBH_Set_Idle_Blocking (pcore, pdev, i, 0, 0); if (status == USBH_OK) { dbg_printf(DBGMODE_DEBUG, "USBH_Set_Idle_Blocking[only %d] OK: 0x%04X\r\n", 0, status); } else if(status == USBH_NOT_SUPPORTED || status == USBH_STALL) { dbg_printf(DBGMODE_DEBUG, "USBH_Set_Idle_Blocking[only %d] NOT SUPPORTED\r\n", 0); } else { dbg_printf(DBGMODE_ERR, "USBH_Set_Idle_Blocking[only %d] failed status: 0x%04X\r\n", 0, status); USBH_ErrorHandle(pcore, pdev, status); } } } if (pdev->device_prop.Dev_Desc.idVendor == SONY_VID && pdev->device_prop.Dev_Desc.idProduct == DUALSHOCK4_PID) { // TODO } else { status = USBH_Set_Protocol_Blocking(pcore, pdev, i, 0); // this sets the protocol = "report" if (status == USBH_OK) { dbg_printf(DBGMODE_DEBUG, "USBH_Set_Protocol_Blocking OK: 0x%04X\r\n", status); } else { dbg_printf(DBGMODE_ERR, "USBH_Set_Protocol_Blocking failed status: 0x%04X\r\n", status); USBH_ErrorHandle(pcore, pdev, status); } } } if (isHid == 0) { // none of the interfaces are HID free(pdev->Usr_Data); pdev->Usr_Data = 0; pdev->cb = &USBH_Dev_CB_Default; // this will cause the device to not be serviced } if (HID_Data->init_handler != 0) { HID_Data->init_handler(pcore, pdev); } USBH_Dev_HID_Cnt++; }
void USBH_Dev_Hub_EnumerationDone(USB_OTG_CORE_HANDLE *pcore , USBH_DEV *pdev) { dbg_printf(DBGMODE_TRACE, "Hub_EnumerationDone \r\n"); if (pdev->Usr_Data != 0) { free(pdev->Usr_Data); pdev->Usr_Data = 0; } pdev->Usr_Data = calloc(1, sizeof(Hub_Data_t)); Hub_Data_t* Hub_Data = pdev->Usr_Data; uint8_t maxEP = ( (pdev->device_prop.Itf_Desc[0].bNumEndpoints <= USBH_MAX_NUM_ENDPOINTS) ? pdev->device_prop.Itf_Desc[0].bNumEndpoints : USBH_MAX_NUM_ENDPOINTS); for (uint8_t num=0; num < maxEP; num++) { USBH_EpDesc_TypeDef* epDesc = &(pdev->device_prop.Ep_Desc[0][num]); if ((epDesc->bmAttributes & EP_TYPE_MSK) == USB_EP_TYPE_INTR && (epDesc->bEndpointAddress & USB_EP_DIR_MSK) == USB_EP_DIR_IN) { //if (epDesc->bInterval > 50) epDesc->bInterval = 50; Hub_Data->intInEpIo = USBH_DevIO_Manager_New(pcore, pdev, epDesc, #ifdef HUB_ENABLE_DYNAMIC_HC_ALLOC 1 #else 0 #endif , USBH_Dev_Hub_DataHandler, 0); Hub_Data->intInEpIo->force_poll_interval = 1; Hub_Data->intInEpIo->timeout = 10; } } if (Hub_Data->intInEpIo == 0) { dbg_printf(DBGMODE_ERR, "Hub %s has no interrupt-in endpoints!\r\n", USBH_Dev_DebugPrint(pdev, 0)); } // the old example HID code used a state machine to perform the sequence of requests, but here we will just do everything in a sequence // get the hub descriptor so we know the number of ports available USBH_Status status = USBH_GetDescriptor_Blocking(pcore, pdev, USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_CLASS, USB_DESC_HUB, 0, pcore->host.Rx_Buffer, USB_HUB_DESC_SIZE ); if (status != USBH_OK) { dbg_printf(DBGMODE_ERR, "Hub_EnumerationDone GetDescriptor failed, status 0x%02X \r\n", status); USBH_ErrorHandle(pcore, pdev, status); return; } Hub_Data->num_ports = pcore->host.Rx_Buffer[2]; //dbg_printf(DBGMODE_DEBUG, "\tbDescriptorType = 0x%02X\r\n", pcore->host.Rx_Buffer[1]); dbg_printf(DBGMODE_DEBUG, "\tnum_ports = %d\r\n", Hub_Data->num_ports); vcp_printf("Hub V%04XP%04XA%d Enumerated, %d ports\r\n", pdev->device_prop.Dev_Desc.idVendor, pdev->device_prop.Dev_Desc.idProduct, pdev->device_prop.address, Hub_Data->num_ports); // allocate memory for the children devices if (Hub_Data->children != 0) { free(Hub_Data->children); Hub_Data->children = 0; } Hub_Data->children = calloc(Hub_Data->num_ports, sizeof(USBH_DEV*)); // iterate all the ports for (int pn = 0; pn < Hub_Data->num_ports; pn++) { Hub_Data->children[pn] = 0; // reset uint16_t wps, wpc; status = USBH_Dev_Hub_GetPortStatus(pcore, pdev, pn, &wps, &wpc); if (status != USBH_OK) { dbg_printf(DBGMODE_ERR, "Hub_EnumerationDone GetPortStatus (pn %d) failed, status 0x%02X \r\n", pn + 1, status); USBH_ErrorHandle(pcore, pdev, status); continue; } status = USBH_Dev_Hub_SetPortFeature(pcore, pdev, pn, HUBREQ_PORT_POWER); if (status != USBH_OK) { dbg_printf(DBGMODE_ERR, "Hub_EnumerationDone SetPortFeature (pn %d) failed, status 0x%02X \r\n", pn + 1, status); USBH_ErrorHandle(pcore, pdev, status); continue; } } // wait for power ready char pwrRdy; volatile int pwrTries = 700 / Hub_Data->num_ports; do { pwrRdy = 1; for (int pn = 0; pn < Hub_Data->num_ports; pn++) { uint16_t wps, wpc; status = USBH_Dev_Hub_GetPortStatus(pcore, pdev, pn, &wps, &wpc); if (status != USBH_OK) { dbg_printf(DBGMODE_ERR, "Hub_EnumerationDone GetPortStatus (pn %d) failed, status 0x%02X \r\n", pn + 1, status); //USBH_ErrorHandle(pcore, pdev, status); continue; } if (wps & (1 << HUBWPORTSTATUS_POWER_BIT) == 0) { pwrRdy = 0; } } } while (pwrRdy == 0 && pwrTries--); if (pwrRdy != 0) { dbg_printf(DBGMODE_TRACE, "Hub_EnumerationDone all port power ready \r\n"); } else { dbg_printf(DBGMODE_ERR, "Hub_EnumerationDone error, power not ready \r\n"); } vcp_printf("%s:Hub Ready, Ports: %d \r\n", USBH_Dev_DebugPrint(pdev, 0), Hub_Data->num_ports); }
/** * @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)&& (phost->gState != HOST_IDLE)) { printf("check for Host port events\r\n"); if(phost->gState != HOST_DEV_DISCONNECTED) { phost->gState = HOST_DEV_DISCONNECTED; } } switch (phost->gState) { case HOST_IDLE : if (HCD_IsDeviceConnected(pdev)) { printf("HOST_DEV_ATTACHED is enter\r\n"); phost->gState = HOST_DEV_ATTACHED; USB_OTG_BSP_mDelay(100); } 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) { printf("HOST_DEV_ATTACHED state reset device"); phost->usr_cb->ResetDevice(); /* Wait for USB USBH_ISR_PrtEnDisableChange() 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); } // printfpdev_reg(pdev); break; case HOST_ENUMERATION: // printfpdev_reg(pdev); // printf(" in HOST_ENUMERATION state\r\n "); /* Check for enumeration status */ if ( USBH_HandleEnum(pdev , phost) == USBH_OK) { printf("HOST_ENUMERATION state enumeration is 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; } 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) { printf("HOST_USR_INPUT state : user_input is ok\r\n"); if((phost->class_cb->Init(pdev, phost))\ == USBH_OK) { phost->gState = HOST_CLASS_REQUEST; } } // printf("GINTSTS :%X\r\n",(pdev->regs.GREGS->GINTSTS)); break; case HOST_CLASS_REQUEST: /* process class standard contol requests state machine */ status = phost->class_cb->Requests(pdev, phost); if(status == USBH_OK) { printf("HOST_CLASS_REQUEST state : contol requests is ok and host class is enter\r\n"); phost->gState = HOST_CLASS; #if 0 // USB_OTG_WRITE_REG32(&pdev->regs.HREGS->HFNUM,0X43FD039B); printf("GRXSTSR: %X\r\n", USB_OTG_READ_REG32(&pdev->regs.GREGS->GRXSTSR)); printf("HNPTXSTS: %X\r\n", USB_OTG_READ_REG32(&pdev->regs.GREGS->HNPTXSTS)); printf("HFNUM: %X\r\n", USB_OTG_READ_REG32(&pdev->regs.HREGS->HFNUM)); printf("HNPTXSTS: %X\r\n", USB_OTG_READ_REG32(&pdev->regs.GREGS->HNPTXSTS)); printf("DIEPTSIZ: %X\r\n", USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[8]->DIEPCTL )); printf("DIEPDMA: %X\r\n", USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[8]->DIEPDMA )); printfpdev_reg(pdev); #endif } 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 */ printf("HOST_CTRL_XFER\r\n"); USBH_HandleControl(pdev, phost); break; case HOST_SUSPENDED: printf("HOST_SUSPENDED\r\n"); break; case HOST_ERROR_STATE: /* Re-Initilaize 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();//user µ÷ÓÃ /* 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; // NVIC_SystemReset(); break; default : break; } }