{
volatile USBH_Status status = USBH_FAIL;
/* 检测端口是否连接 */
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) //switch~case选择结构,逐个执行
{
case HOST_IDLE :
if (HCD_IsDeviceConnected(pdev)) //检测设备是否连接,若设备连接
{
phost->gState = HOST_WAIT_PRT_ENABLED;
/*延时一段时间,是设备电源稳定 */
USB_OTG_BSP_mDelay(100);
/* 发送端口复位指令T */
HCD_ResetPort(pdev);
/* 打印设备复位*/
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); //给USB设备分配输出通道
phost->Control.hc_num_in = USBH_Alloc_Channel(pdev, 0x80); //给USB设备分配输入通道
/* 复位USB设备 */
if ( HCD_ResetPort(pdev) == 0) //执行USB设备复位,若成功复位
{
phost->usr_cb->ResetDevice();//打印设备复位
/* 主机已经准备好枚举*/
phost->device_prop.speed = HCD_GetCurrentSpeed(pdev);//检测设备的速度
phost->gState = HOST_ENUMERATION;
phost->usr_cb->DeviceSpeedDetected(phost->device_prop.speed);//打印设备的速度
/* 打开输入控制通道*/
USBH_Open_Channel (pdev,
phost->Control.hc_num_in,
phost->device_prop.address,
phost->device_prop.speed,
EP_TYPE_CTRL,
phost->Control.ep0size);
/* 打开输出控制通道 */
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:
/*进入枚举过程 */
if ( USBH_HandleEnum(pdev , phost) == USBH_OK) //执行枚举函数,如枚举成功
{
/* 如果枚举完成,则函数返回USBH_OK */
/* 打印设备枚举完成 */
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: //用户输入确认,这个函数返回用户的确认的确认信息
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: //获取设备的类,调用函数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 ://如果USB设备没有连接
/* 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;
}
}
在上面函数执行过程中,执行了枚举函数USBH_HandleEnum(),对于该函数,其函数解析如下:
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;
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)
{
/* before getting full config descriptor, check if it does not exceed
buffer size allocated to config descriptor USBH_MAX_DATA_BUFFER
in the usbh_conf.h*/
if (phost->device_prop.Cfg_Desc.wTotalLength <= USBH_MAX_DATA_BUFFER)
{
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;
}