/** * 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_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); }
TM_USB_MSCHOST_Result_t TM_USB_MSCHOST_DeInit(void) { /* Deinit USB host */ USBH_DeInit(&USB_OTG_MSC_Core, &USB_Host); /* Return OK */ return TM_USB_MSCHOST_Result_Disconnected; }
/** * @brief USBH_Disconnect * USB Disconnect callback function from the Interrupt. * @param selected device * @retval none */ rt_uint8_t susb_disconnect (USB_OTG_CORE_HANDLE *pdev) { struct uhost_msg msg; pdev->host.ConnSts = 0; rt_kprintf("susb_disconnect\n"); USBH_DeInit(&USB_OTG_Core , &USB_Host); USBH_DeAllocate_AllChannel(&USB_OTG_Core); USB_Host.gState = HOST_IDLE; root_hub.port_status[0] |= PORT_CCSC; root_hub.port_status[0] &= ~PORT_CCS; msg.type = USB_MSG_CONNECT_CHANGE; msg.content.uhub = &root_hub; rt_usb_post_event(&msg, sizeof(struct uhost_msg)); return 0; }
void USBH_Dev_Hub_DeviceDisconnected(USB_OTG_CORE_HANDLE *pcore , USBH_DEV *pdev) { dbg_printf(DBGMODE_TRACE, "USBH_Dev_Hub_DeviceDisconnected\r\n"); Hub_Data_t* Hub_Data = pdev->Usr_Data; // iterate all the ports for (int pn = 0; pn < Hub_Data->num_ports && Hub_Data->children != 0; pn++) { if (Hub_Data->children[pn] != 0) { // disconnect event for all children ((USBH_Device_cb_TypeDef*)Hub_Data->children[pn]->cb)->DeviceDisconnected(pcore, pdev); USBH_DeInit(pcore, Hub_Data->children[pn]); // frees channels ((USBH_Device_cb_TypeDef*)Hub_Data->children[pn]->cb)->DeInit(pcore, Hub_Data->children[pn]); ((USBH_Device_cb_TypeDef*)Hub_Data->children[pn]->cb)->DeInitDev(pcore, Hub_Data->children[pn]); // this is the one that frees memory //free(Hub_Data->children[pn]); Hub_Data->children[pn] = 0; } } if (Hub_Data->children != 0) { free(Hub_Data->children); Hub_Data->children = 0; } }
/** * @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_Hub_DataHandler(void* p_io, uint8_t* data, uint16_t len) { USBH_DevIO_t* p_in = p_io; USBH_DEV* pdev = p_in->pdev; USB_OTG_CORE_HANDLE* pcore = p_in->pcore; Hub_Data_t* Hub_Data = pdev->Usr_Data; USBH_Status errCode; int8_t alloc = 0; USBH_Dev_AllocControl(pcore, pdev); // when a device connects or disconnects from the hub, the hub will issue an interrupt-in message // iterate all the ports for (int pn = 0; pn < Hub_Data->num_ports; pn++) { int pnp1 = pn + 1; uint8_t bitIdx = pnp1 % 8; uint8_t byteIdx = pnp1 / 8; // did this port cause the event? if (data[byteIdx] & (1 << bitIdx)) { if (Hub_Data->port_busy != 0 && Hub_Data->port_busy != pnp1) { // we can only handle one new device at a time, or else they all listen to address 0 continue; } if (alloc == 0) { alloc = USBH_Dev_AllocControl(p_in->pcore, p_in->pdev); } uint16_t wPortStatus, wPortChange; errCode = USBH_Dev_Hub_GetPortStatus(pcore, pdev, pn, &wPortStatus, &wPortChange); if (errCode != USBH_OK) { dbg_printf(DBGMODE_ERR, "USBH_Dev_Hub_Handle_InterruptIn GetPortStatus (pn %d) failed (status 0x%04X) \r\n", pn, errCode); if (errCode == USBH_STALL || errCode == USBH_NOT_SUPPORTED) { errCode = USBH_ClrFeature_Blocking(pcore, pdev, 0, 0); } continue; } dbg_printf(DBGMODE_DEBUG, "Hub_Handle_InterruptIn Hub_GetPortStatus, pn: %d, s: 0x%04X, c: 0x%04X\r\n", pnp1, wPortStatus, wPortChange); if ((wPortStatus & (1 << HUBWPORTSTATUS_POWER_BIT)) == 0) { errCode = USBH_Dev_Hub_SetPortFeature(pcore, pdev, pnp1, HUBREQ_PORT_POWER); if (errCode == USBH_STALL || errCode == USBH_NOT_SUPPORTED) { errCode = USBH_ClrFeature_Blocking(pcore, pdev, 0, 0); } } if ((wPortStatus & (1 << HUBWPORTCHANGE_ENABLED_BIT)) == 0) { errCode = USBH_Dev_Hub_SetPortFeature(pcore, pdev, pn, HUBREQ_PORT_ENABLE); if (errCode == USBH_STALL || errCode == USBH_NOT_SUPPORTED) { errCode = USBH_ClrFeature_Blocking(pcore, pdev, 0, 0); } } if ((wPortChange & (1 << HUBWPORTCHANGE_RESET_BIT)) != 0) { errCode = USBH_Dev_Hub_ClearPortFeature(pcore, pdev, pn, HUBREQ_C_PORT_RESET, 0); if (errCode == USBH_STALL || errCode == USBH_NOT_SUPPORTED) { errCode = USBH_ClrFeature_Blocking(pcore, pdev, 0, 0); } } if ((wPortChange & (1 << HUBWPORTCHANGE_CONNSTAT_BIT)) != 0) { errCode = USBH_Dev_Hub_ClearPortFeature(pcore, pdev, pn, HUBREQ_C_PORT_CONNECTION, 0); if (errCode == USBH_STALL || errCode == USBH_NOT_SUPPORTED) { errCode = USBH_ClrFeature_Blocking(pcore, pdev, 0, 0); } } if ((wPortChange & (1 << HUBWPORTCHANGE_ENABLED_BIT)) != 0) { errCode = USBH_Dev_Hub_ClearPortFeature(pcore, pdev, pn, HUBREQ_C_PORT_ENABLE, 0); if (errCode == USBH_STALL || errCode == USBH_NOT_SUPPORTED) { errCode = USBH_ClrFeature_Blocking(pcore, pdev, 0, 0); } } if ((wPortStatus & (1 << HUBWPORTSTATUS_RESET_BIT)) != 0) { if (Hub_Data->children[pn] != 0 && Hub_Data->children[pn]->gState == HOST_IDLE) { Hub_Data->children[pn]->gState = HOST_DEV_RESET_PENDING; } } else { if (((wPortStatus & (1 << HUBWPORTSTATUS_CURCONN_BIT)) == 0 || (wPortStatus & (1 << HUBWPORTSTATUS_ENABLED_BIT)) == 0) && Hub_Data->children[pn] != 0 && Hub_Data->children[pn]->cb != 0 && Hub_Data->children[pn]->gState != HOST_IDLE && Hub_Data->children[pn]->gState != HOST_DEV_RESET_PENDING) { dbg_printf(DBGMODE_TRACE, "Hub %s disconnected device (pn %d)\r\n", USBH_Dev_DebugPrint(pdev, 0), pnp1); vcp_printf("Hub %s Lost Device on Port %d\r\n", USBH_Dev_DebugPrint(pdev, 0), pnp1); ((USBH_Device_cb_TypeDef*)Hub_Data->children[pn]->cb)->DeviceDisconnected(pcore, pdev); USBH_DeInit(pcore, Hub_Data->children[pn]); // frees channels ((USBH_Device_cb_TypeDef*)Hub_Data->children[pn]->cb)->DeInit(pcore, Hub_Data->children[pn]); ((USBH_Device_cb_TypeDef*)Hub_Data->children[pn]->cb)->DeInitDev(pcore, Hub_Data->children[pn]); // this is the one that frees memory free(Hub_Data->children[pn]); Hub_Data->children[pn] = 0; } else if ((wPortStatus & (1 << HUBWPORTSTATUS_CURCONN_BIT)) != 0) { if ((wPortStatus & (1 << HUBWPORTSTATUS_RESET_BIT)) == 0 && (wPortStatus & (1 << HUBWPORTSTATUS_ENABLED_BIT)) != 0 && Hub_Data->children[pn] != 0 && Hub_Data->children[pn]->cb != 0 && (Hub_Data->children[pn]->gState == HOST_DEV_RESET_PENDING || Hub_Data->children[pn]->gState == HOST_IDLE)) { if (((USBH_Device_cb_TypeDef*)Hub_Data->children[pn]->cb)->ResetDevice != 0) ((USBH_Device_cb_TypeDef*)Hub_Data->children[pn]->cb)->ResetDevice(pcore, pdev); Hub_Data->children[pn]->device_prop.speed = (wPortStatus & (1 << 9)) ? HPRT0_PRTSPD_LOW_SPEED : HPRT0_PRTSPD_FULL_SPEED; // if bit 9 is 1, then it is low speed (0x02), or else it is full speed (0x01) if (((USBH_Device_cb_TypeDef*)Hub_Data->children[pn]->cb)->DeviceSpeedDetected != 0) ((USBH_Device_cb_TypeDef*)Hub_Data->children[pn]->cb)->DeviceSpeedDetected(pcore, Hub_Data->children[pn], Hub_Data->children[pn]->device_prop.speed); Hub_Data->children[pn]->gState = HOST_DEV_DELAY; USBH_Dev_Reset_Timer = systick_1ms_cnt; Hub_Data->children[pn]->device_prop.address = 0; // new attached devices to a hub is always address 0 Hub_Data->port_busy = pnp1; Hub_Data->intInEpIo->enabled = 0; // we are allowed to pass this on to the upper state machine now, it will seem like it was attached normally dbg_printf(DBGMODE_TRACE, "Hub passed new device (pn %d) to upper state machine \r\n", pnp1); vcp_printf("Hub %s New Device on Port %d\r\n", USBH_Dev_DebugPrint(pdev, 0), pnp1); } else if (Hub_Data->children[pn] == 0) { errCode = USBH_Dev_Hub_SetPortFeature(pcore, pdev, pn, HUBREQ_PORT_RESET); Hub_Data->children[pn] = calloc(1, sizeof(USBH_DEV)); Hub_Data->children[pn]->Parent = pdev; Hub_Data->children[pn]->gState = HOST_IDLE; Hub_Data->children[pn]->gStateBkp = HOST_IDLE; Hub_Data->children[pn]->EnumState = ENUM_IDLE; Hub_Data->children[pn]->RequestState = CMD_SEND; Hub_Data->children[pn]->device_prop.address = USBH_DEVICE_ADDRESS_DEFAULT; // this better be 0 Hub_Data->children[pn]->device_prop.speed = HPRT0_PRTSPD_LOW_SPEED; Hub_Data->children[pn]->port_num = pnp1; Hub_Data->children[pn]->Control.hc_num_in = -1; Hub_Data->children[pn]->Control.hc_num_out = -1; Hub_Data->children[pn]->Control.hc_in_tgl_in = -1; Hub_Data->children[pn]->Control.hc_in_tgl_out = -1; Hub_Data->children[pn]->Control.hc_out_tgl_in = -1; Hub_Data->children[pn]->Control.hc_out_tgl_out = -1; Hub_Data->children[pn]->Control.state = CTRL_IDLE; Hub_Data->children[pn]->Control.ep0size = USB_OTG_MAX_EP0_SIZE; Hub_Data->children[pn]->cb = (void*)&USBH_Dev_CB_Default; Hub_Data->port_busy = pnp1; dbg_printf(DBGMODE_TRACE, "Hub %s created new child (pn %d) \r\n", USBH_Dev_DebugPrint(pdev, 0), pnp1); } } } } } if (alloc != 0) { USBH_Dev_FreeControl(p_in->pcore, p_in->pdev); } }
/** * @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; } }