/** * @brief USBH_HandleEnum * This function includes the complete enumeration process * @param pdev: Selected device * @retval USBH_Status */ static USBH_Status USBH_HandleEnum(USB_OTG_CORE_HANDLE *pdev, USBH_HOST *phost) { USBH_Status Status = USBH_BUSY; uint8_t Local_Buffer[64]; switch (phost->EnumState) { case ENUM_IDLE: /* Get Device Desc for only 1st 8 bytes : To get EP0 MaxPacketSize */ if ( USBH_Get_DevDesc(pdev , phost, 8) == USBH_OK) { phost->Control.ep0size = phost->device_prop.Dev_Desc.bMaxPacketSize; /* Issue Reset */ HCD_ResetPort(pdev); phost->EnumState = ENUM_GET_FULL_DEV_DESC; /* modify control channels configuration for MaxPacket size */ USBH_Modify_Channel (pdev, phost->Control.hc_num_out, 0, 0, 0, phost->Control.ep0size); USBH_Modify_Channel (pdev, phost->Control.hc_num_in, 0, 0, 0, phost->Control.ep0size); } break; case ENUM_GET_FULL_DEV_DESC: /* Get FULL Device Desc */ if ( USBH_Get_DevDesc(pdev, phost, USB_DEVICE_DESC_SIZE)\ == USBH_OK) { /* user callback for device descriptor available */ phost->usr_cb->DeviceDescAvailable(&phost->device_prop.Dev_Desc); phost->EnumState = ENUM_SET_ADDR; } break; case ENUM_SET_ADDR: /* set address */ if ( USBH_SetAddress(pdev, phost, USBH_DEVICE_ADDRESS) == USBH_OK) { USB_OTG_BSP_mDelay(2); phost->device_prop.address = USBH_DEVICE_ADDRESS; /* user callback for device address assigned */ phost->usr_cb->DeviceAddressAssigned(); phost->EnumState = ENUM_GET_CFG_DESC; /* modify control channels to update device address */ USBH_Modify_Channel (pdev, phost->Control.hc_num_in, phost->device_prop.address, 0, 0, 0); USBH_Modify_Channel (pdev, phost->Control.hc_num_out, phost->device_prop.address, 0, 0, 0); } break; case ENUM_GET_CFG_DESC: /* get standard configuration descriptor */ if ( USBH_Get_CfgDesc(pdev, phost, USB_CONFIGURATION_DESC_SIZE) == USBH_OK) { phost->EnumState = ENUM_GET_FULL_CFG_DESC; } break; case ENUM_GET_FULL_CFG_DESC: /* get FULL config descriptor (config, interface, endpoints) */ if (USBH_Get_CfgDesc(pdev, phost, phost->device_prop.Cfg_Desc.wTotalLength) == USBH_OK) { /* User callback for configuration descriptors available */ phost->usr_cb->ConfigurationDescAvailable(&phost->device_prop.Cfg_Desc, phost->device_prop.Itf_Desc, phost->device_prop.Ep_Desc[0]); phost->EnumState = ENUM_GET_MFC_STRING_DESC; } break; case ENUM_GET_MFC_STRING_DESC: if (phost->device_prop.Dev_Desc.iManufacturer != 0) { /* Check that Manufacturer String is available */ if ( USBH_Get_StringDesc(pdev, phost, phost->device_prop.Dev_Desc.iManufacturer, Local_Buffer , 0xff) == USBH_OK) { /* User callback for Manufacturing string */ phost->usr_cb->ManufacturerString(Local_Buffer); phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC; } } else { phost->usr_cb->ManufacturerString("N/A"); phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC; } break; case ENUM_GET_PRODUCT_STRING_DESC: if (phost->device_prop.Dev_Desc.iProduct != 0) { /* Check that Product string is available */ if ( USBH_Get_StringDesc(pdev, phost, phost->device_prop.Dev_Desc.iProduct, Local_Buffer, 0xff) == USBH_OK) { /* User callback for Product string */ phost->usr_cb->ProductString(Local_Buffer); phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC; } } else { phost->usr_cb->ProductString("N/A"); phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC; } break; case ENUM_GET_SERIALNUM_STRING_DESC: if (phost->device_prop.Dev_Desc.iSerialNumber != 0) { /* Check that Serial number string is available */ if ( USBH_Get_StringDesc(pdev, phost, phost->device_prop.Dev_Desc.iSerialNumber, Local_Buffer, 0xff) == USBH_OK) { /* User callback for Serial number string */ phost->usr_cb->SerialNumString(Local_Buffer); phost->EnumState = ENUM_SET_CONFIGURATION; } } else { phost->usr_cb->SerialNumString("N/A"); phost->EnumState = ENUM_SET_CONFIGURATION; } break; case ENUM_SET_CONFIGURATION: /* set configuration (default config) */ if (USBH_SetCfg(pdev, phost, phost->device_prop.Cfg_Desc.bConfigurationValue) == USBH_OK) { phost->EnumState = ENUM_DEV_CONFIGURED; } break; case ENUM_DEV_CONFIGURED: /* user callback for enumeration done */ Status = USBH_OK; break; default: break; } return Status; }
/** * @brief USBH_HandleEnum * This function includes the complete enumeration process * @param phost: Host Handle * @retval USBH_Status */ static USBH_StatusTypeDef USBH_HandleEnum (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef Status = USBH_BUSY; switch (phost->EnumState) { case ENUM_IDLE: /* Get Device Desc for only 1st 8 bytes : To get EP0 MaxPacketSize */ if ( USBH_Get_DevDesc(phost, 8) == USBH_OK) { phost->Control.pipe_size = phost->device.DevDesc.bMaxPacketSize; phost->EnumState = ENUM_GET_FULL_DEV_DESC; /* modify control channels configuration for MaxPacket size */ USBH_OpenPipe (phost, phost->Control.pipe_in, 0x80, phost->device.address, phost->device.speed, USBH_EP_CONTROL, phost->Control.pipe_size); /* Open Control pipes */ USBH_OpenPipe (phost, phost->Control.pipe_out, 0x00, phost->device.address, phost->device.speed, USBH_EP_CONTROL, phost->Control.pipe_size); } break; case ENUM_GET_FULL_DEV_DESC: /* Get FULL Device Desc */ if ( USBH_Get_DevDesc(phost, USB_DEVICE_DESC_SIZE)== USBH_OK) { USBH_UsrLog("PID: %xh", phost->device.DevDesc.idProduct ); USBH_UsrLog("VID: %xh", phost->device.DevDesc.idVendor ); phost->EnumState = ENUM_SET_ADDR; } break; case ENUM_SET_ADDR: /* set address */ if ( USBH_SetAddress(phost, USBH_DEVICE_ADDRESS) == USBH_OK) { USBH_Delay(2); phost->device.address = USBH_DEVICE_ADDRESS; /* user callback for device address assigned */ USBH_UsrLog("Address (#%d) assigned.", phost->device.address); phost->EnumState = ENUM_GET_CFG_DESC; /* modify control channels to update device address */ USBH_OpenPipe (phost, phost->Control.pipe_in, 0x80, phost->device.address, phost->device.speed, USBH_EP_CONTROL, phost->Control.pipe_size); /* Open Control pipes */ USBH_OpenPipe (phost, phost->Control.pipe_out, 0x00, phost->device.address, phost->device.speed, USBH_EP_CONTROL, phost->Control.pipe_size); } break; case ENUM_GET_CFG_DESC: /* get standard configuration descriptor */ if ( USBH_Get_CfgDesc(phost, USB_CONFIGURATION_DESC_SIZE) == USBH_OK) { phost->EnumState = ENUM_GET_FULL_CFG_DESC; } break; case ENUM_GET_FULL_CFG_DESC: /* get FULL config descriptor (config, interface, endpoints) */ if (USBH_Get_CfgDesc(phost, phost->device.CfgDesc.wTotalLength) == USBH_OK) { phost->EnumState = ENUM_GET_MFC_STRING_DESC; } break; case ENUM_GET_MFC_STRING_DESC: if (phost->device.DevDesc.iManufacturer != 0) { /* Check that Manufacturer String is available */ if ( USBH_Get_StringDesc(phost, phost->device.DevDesc.iManufacturer, phost->device.Data , 0xff) == USBH_OK) { /* User callback for Manufacturing string */ USBH_UsrLog("Manufacturer : %s", (char *)phost->device.Data); phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); #endif } } else { USBH_UsrLog("Manufacturer : N/A"); phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); #endif } break; case ENUM_GET_PRODUCT_STRING_DESC: if (phost->device.DevDesc.iProduct != 0) { /* Check that Product string is available */ if ( USBH_Get_StringDesc(phost, phost->device.DevDesc.iProduct, phost->device.Data, 0xff) == USBH_OK) { /* User callback for Product string */ USBH_UsrLog("Product : %s", (char *)phost->device.Data); phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC; } } else { USBH_UsrLog("Product : N/A"); phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); #endif } break; case ENUM_GET_SERIALNUM_STRING_DESC: if (phost->device.DevDesc.iSerialNumber != 0) { /* Check that Serial number string is available */ if ( USBH_Get_StringDesc(phost, phost->device.DevDesc.iSerialNumber, phost->device.Data, 0xff) == USBH_OK) { /* User callback for Serial number string */ USBH_UsrLog("Serial Number : %s", (char *)phost->device.Data); Status = USBH_OK; } } else { USBH_UsrLog("Serial Number : N/A"); Status = USBH_OK; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0); #endif } break; default: break; } return Status; }