|
发表于 2025-5-29 18:09:12
|
显示全部楼层
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;
}
/**
* @brief USBH_HandleControl
* Handles the USB control transfer state machine
* @param pdev: Selected device
* @retval Status
*/
USBH_Status USBH_HandleControl (USB_OTG_CORE_HANDLE *pdev, USBH_HOST *phost)
{
uint8_t direction;
static uint16_t timeout = 0;
USBH_Status status = USBH_OK;
URB_STATE URB_Status = URB_IDLE;
phost->Control.status = CTRL_START;
switch (phost->Control.state)
{
case CTRL_SETUP:
/* send a SETUP packet */
USBH_CtlSendSetup (pdev,
phost->Control.setup.d8 ,
phost->Control.hc_num_out);
phost->Control.state = CTRL_SETUP_WAIT;
break;
case CTRL_SETUP_WAIT:
URB_Status = HCD_GetURB_State(pdev , phost->Control.hc_num_out);
/* case SETUP packet sent successfully */
if(URB_Status == URB_DONE)
{
direction = (phost->Control.setup.b.bmRequestType & USB_REQ_DIR_MASK);
/* check if there is a data stage */
if (phost->Control.setup.b.wLength.w != 0 )
{
timeout = DATA_STAGE_TIMEOUT;
if (direction == USB_D2H)
{
/* Data Direction is IN */
phost->Control.state = CTRL_DATA_IN;
}
else
{
/* Data Direction is OUT */
phost->Control.state = CTRL_DATA_OUT;
}
}
/* No DATA stage */
else
{
timeout = NODATA_STAGE_TIMEOUT;
/* If there is No Data Transfer Stage */
if (direction == USB_D2H)
{
/* Data Direction is IN */
phost->Control.state = CTRL_STATUS_OUT;
}
else
{
/* Data Direction is OUT */
phost->Control.state = CTRL_STATUS_IN;
}
}
/* Set the delay timer to enable timeout for data stage completion */
phost->Control.timer = HCD_GetCurrentFrame(pdev);
}
else if(URB_Status == URB_ERROR)
{
phost->Control.state = CTRL_ERROR;
phost->Control.status = CTRL_XACTERR;
}
break;
case CTRL_DATA_IN:
/* Issue an IN token */
USBH_CtlReceiveData(pdev,
phost->Control.buff,
phost->Control.length,
phost->Control.hc_num_in);
phost->Control.state = CTRL_DATA_IN_WAIT;
break;
case CTRL_DATA_IN_WAIT:
URB_Status = HCD_GetURB_State(pdev , phost->Control.hc_num_in);
/* check is DATA packet transferred successfully */
if (URB_Status == URB_DONE)
{
phost->Control.state = CTRL_STATUS_OUT;
}
/* manage error cases*/
if (URB_Status == URB_STALL)
{
/* In stall case, return to previous machine state*/
phost->gState = phost->gStateBkp;
phost->Control.state = CTRL_STALLED;
}
else if (URB_Status == URB_ERROR)
{
/* Device error */
phost->Control.state = CTRL_ERROR;
}
else if ((HCD_GetCurrentFrame(pdev)- phost->Control.timer) > timeout)
{
/* timeout for IN transfer */
phost->Control.state = CTRL_ERROR;
}
break;
case CTRL_DATA_OUT:
/* Start DATA out transfer (only one DATA packet)*/
pdev->host.hc[phost->Control.hc_num_out].toggle_out = 1;
USBH_CtlSendData (pdev,
phost->Control.buff,
phost->Control.length ,
phost->Control.hc_num_out);
phost->Control.state = CTRL_DATA_OUT_WAIT;
break;
case CTRL_DATA_OUT_WAIT:
URB_Status = HCD_GetURB_State(pdev , phost->Control.hc_num_out);
if (URB_Status == URB_DONE)
{ /* If the Setup Pkt is sent successful, then change the state */
phost->Control.state = CTRL_STATUS_IN;
}
/* handle error cases */
else if (URB_Status == URB_STALL)
{
/* In stall case, return to previous machine state*/
phost->gState = phost->gStateBkp;
phost->Control.state = CTRL_STALLED;
}
else if (URB_Status == URB_NOTREADY)
{
/* Nack received from device */
phost->Control.state = CTRL_DATA_OUT;
}
else if (URB_Status == URB_ERROR)
{
/* device error */
phost->Control.state = CTRL_ERROR;
}
break;
case CTRL_STATUS_IN:
/* Send 0 bytes out packet */
USBH_CtlReceiveData (pdev,
0,
0,
phost->Control.hc_num_in);
phost->Control.state = CTRL_STATUS_IN_WAIT;
break;
case CTRL_STATUS_IN_WAIT:
URB_Status = HCD_GetURB_State(pdev , phost->Control.hc_num_in);
if ( URB_Status == URB_DONE)
{ /* Control transfers completed, Exit the State Machine */
phost->gState = phost->gStateBkp;
phost->Control.state = CTRL_COMPLETE;
}
else if (URB_Status == URB_ERROR)
{
phost->Control.state = CTRL_ERROR;
}
else if((HCD_GetCurrentFrame(pdev)\
- phost->Control.timer) > timeout)
{
phost->Control.state = CTRL_ERROR;
}
else if(URB_Status == URB_STALL)
{
/* Control transfers completed, Exit the State Machine */
phost->gState = phost->gStateBkp;
phost->Control.state = CTRL_STALLED;
status = USBH_NOT_SUPPORTED;
}
break;
case CTRL_STATUS_OUT:
pdev->host.hc[phost->Control.hc_num_out].toggle_out ^= 1;
USBH_CtlSendData (pdev,
0,
0,
phost->Control.hc_num_out);
phost->Control.state = CTRL_STATUS_OUT_WAIT;
break;
case CTRL_STATUS_OUT_WAIT:
URB_Status = HCD_GetURB_State(pdev , phost->Control.hc_num_out);
if (URB_Status == URB_DONE)
{
phost->gState = phost->gStateBkp;
phost->Control.state = CTRL_COMPLETE;
}
else if (URB_Status == URB_NOTREADY)
{
phost->Control.state = CTRL_STATUS_OUT;
}
else if (URB_Status == URB_ERROR)
{
phost->Control.state = CTRL_ERROR;
}
break;
case CTRL_ERROR:
/*
After a halt condition is encountered or an error is detected by the
host, a control endpoint is allowed to recover by accepting the next Setup
PID; i.e., recovery actions via some other pipe are not required for control
endpoints. For the Default Control Pipe, a device reset will ultimately be
required to clear the halt or error condition if the next Setup PID is not
accepted.
*/
if (++ phost->Control.errorcount <= USBH_MAX_ERROR_COUNT)
{
/* Do the transmission again, starting from SETUP Packet */
phost->Control.state = CTRL_SETUP;
}
else
{
phost->Control.status = CTRL_FAIL;
phost->gState = phost->gStateBkp;
status = USBH_FAIL;
}
break;
default:
break;
}
return status;
}
/*******************************/
请教个问题,这是ST USB的驱动库,版本是V2.2.0,相对于之前的版本,解决了这个问题“在获取完整的配置描述符之前添加对分配给配置描述符的缓冲区大小的检查,USBH_MAX_DATA_BUFFER定义添加到 usbh_conf.h 中
”,但是我看的代码,这个宏定义和数组大小并没有关联起来,他是如何解决的? |
|