USBH_Process()函数及其子函数USBH_HandleEnum()的解析

void USBH_Process(USB_OTG_CORE_HANDLE *pdev , USBH_HOST *phost)
{
  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;
}





  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
STM32 HOST USB代码 u8 USH_User_App(void) { u32 total,free; u8 res=0; Show_Str(30,140,200,16,"É豸Á¬½Ó³É¹¦!.",16,0); res=exf_getfree("2:",&total,&free); if(res==0) { POINT_COLOR=BLUE;//ÉèÖÃ×ÖÌåΪÀ¶É« LCD_ShowString(30,160,200,16,16,"FATFS OK!"); LCD_ShowString(30,180,200,16,16,"U Disk Total Size: MB"); LCD_ShowString(30,200,200,16,16,"U Disk Free Size: MB"); LCD_ShowNum(174,180,total>>10,5,16); //ÏÔʾUÅÌ×ÜÈÝÁ¿ MB LCD_ShowNum(174,200,free>>10,5,16); } while(HCD_IsDeviceConnected(&USB_OTG_Core))//É豸Á¬½Ó³É¹¦ { LED1=!LED1; delay_ms(200); } POINT_COLOR=RED;//ÉèÖÃ×ÖÌåΪºìÉ« Show_Str(30,140,200,16,"É豸Á¬½ÓÖÐ...",16,0); LCD_Fill(30,160,239,220,WHITE); return res; } int main(void) { u8 t; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//ÉèÖÃϵͳÖжÏÓÅÏȼ¶·Ö×é2 delay_init(168); //³õʼ»¯ÑÓʱº¯Êý uart_init(115200); //³õʼ»¯´®¿Ú²¨ÌØÂÊΪ115200 LED_Init(); //³õʼ»¯ÓëLEDÁ¬½ÓµÄÓ²¼þ½Ó¿Ú KEY_Init(); //°´¼ü LCD_Init(); //³õʼ»¯LCD W25QXX_Init(); //SPI FLASH³õʼ»¯ usmart_dev.init(84); //³õʼ»¯USMART my_mem_init(SRAMIN); //³õʼ»¯ÄÚ²¿ÄÚ´æ³Ø exfuns_init(); //ΪfatfsÏà¹Ø±äÁ¿ÉêÇëÄÚ´æ piclib_init(); //³õʼ»¯»­Í¼ f_mount(fs[0],"0:",1); //¹ÒÔØSD¿¨ f_mount(fs[1],"1:",1); //¹ÒÔØSD¿¨ f_mount(fs[2],"2:",1); //¹ÒÔØUÅÌ POINT_COLOR=RED; while(font_init()) //¼ì²é×Ö¿â { LCD_ShowString(60,50,200,16,16,"Font Error!"); delay_ms(200); LCD_Fill(60,50,240,66,WHITE);//Çå³ýÏÔʾ delay_ms(200); } Show_Str(30,50,200,16,"̽Ë÷ÕßSTM32F407¿ª·¢°å",16,0); Show_Str(30,70,200,16,"USB UÅÌʵÑé",16,0); Show_Str(30,90,200,16,"2014Äê7ÔÂ22ÈÕ",16,0); Show_Str(30,110,200,16,"ÕýµãÔ­×Ó@ALIENTEK",16,0); Show_Str(30,140,200,16,"É豸Á¬½ÓÖÐ...",16,0); //³õʼ»¯USBÖ÷»ú USBH_Init(&USB_OTG_Core,USB_OTG_FS_CORE_ID,&USB_Host,&USBH_MSC_cb,&USR_Callbacks); while(1) { USBH_Process(&USB_OTG_Core, &USB_Host); delay_ms(1); t++; if(t==200) { LED0=!LED0; t=0; } } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值