示例#1
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;
  }

}
示例#2
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;
//	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;
  }

}
示例#4
0
void USBH_Dev_HID_EnumerationDone(USB_OTG_CORE_HANDLE *pcore, USBH_DEV *pdev)
{
	if (pdev->Usr_Data != 0) {
		free(pdev->Usr_Data);
		pdev->Usr_Data = 0;
	}

	uint8_t numIntf = pdev->device_prop.Cfg_Desc.bNumInterfaces;
	char isHid = 0;
	pdev->Usr_Data = calloc(1, sizeof(HID_Data_t));
	HID_Data_t* HID_Data = pdev->Usr_Data;
	HID_Data->io = calloc(numIntf, sizeof(USBH_DevIO_t*));
	HID_Data->ioIdx = 0;

	dbg_printf(DBGMODE_DEBUG, "USBH_Dev_HID_EnumerationDone, bNumInterfaces: %d\r\n", numIntf);

	for (int i = 0; i < numIntf; i++)
	{
		// filter out non-HID class interfaces
		if (pdev->device_prop.Itf_Desc[i].bInterfaceClass != 0x03) {
			continue;
		}

		isHid = 1;

		USBH_DevD2H_DataHandler_t dataHandler = 0;
		HID_Rpt_Parsing_Params_t* parser = 0;
		uint8_t parserEp = 0;

		if (pdev->device_prop.Dev_Desc.idVendor == SONY_VID && pdev->device_prop.Dev_Desc.idProduct == DUALSHOCK3_PID) {
			// DUALSHOCK3
			dataHandler = USBH_DS3_Data_Handler;
			dbg_printf(DBGMODE_TRACE, "Dualshock 3 Detected\r\n");
		}
		else if (pdev->device_prop.Dev_Desc.idVendor == SONY_VID && pdev->device_prop.Dev_Desc.idProduct == DUALSHOCK4_PID) {
			// DUALSHOCK4
			dataHandler = USBH_DS4_Data_Handler;
			HID_Data->init_handler = USBH_DS4_Init_Handler;
			HID_Data->deinit_handler = USBH_DS4_DeInit_Handler;
			HID_Data->custom_task = USBH_DS4_Task;
			dbg_printf(DBGMODE_TRACE, "Dualshock 4 Detected\r\n");
		}
		// TODO handle others, like Xbox controllers
		else {
			// other, probably keyboard or mouse
			parser = malloc(sizeof(HID_Rpt_Parsing_Params_t));
			dataHandler = HID_Default_Data_Handler;
		}

		uint8_t maxEP = ( (pdev->device_prop.Itf_Desc[i].bNumEndpoints <= USBH_MAX_NUM_ENDPOINTS) ?
						pdev->device_prop.Itf_Desc[i].bNumEndpoints :
						USBH_MAX_NUM_ENDPOINTS);

		// assign interrupt endpoints to channels, and polling parameters for the D2H endpoint
		// warning: assume 1 interrupt endpoint per direction
		for (int j = 0; j < maxEP; j++)
		{
			USBH_EpDesc_TypeDef* epDesc = &(pdev->device_prop.Ep_Desc[i][j]);
			if ((epDesc->bmAttributes & EP_TYPE_MSK) == USB_EP_TYPE_INTR)
			{
				if ((epDesc->bEndpointAddress & USB_EP_DIR_MSK) == USB_EP_DIR_IN)
				{
					HID_Data->io[i] = USBH_DevIO_Manager_New(pcore, pdev, epDesc,
#ifdef USBH_HID_ENABLE_DYNAMIC_HC_ALLOC
							1
#else
							0
#endif
							,
							dataHandler, parser
					);
					parserEp = epDesc->bEndpointAddress;
				}
			}
		}

		USBH_Status status;

		if (parser != 0)
		{
			USBH_HIDDesc_TypeDef hidDesc;

			status = USBH_Get_HID_Descriptor_Blocking (pcore, pdev, i);
			if (status == USBH_OK) {
				USBH_ParseHIDDesc(&hidDesc, pcore->host.Rx_Buffer);
				vcp_printf("%sI%d:C%d:HIDDesc:\r\n", USBH_Dev_DebugPrint(pdev, 0), i, USB_HID_DESC_SIZE);
				for (uint8_t k = 0; k < USB_HID_DESC_SIZE; k++) {
					vcp_printf(" 0x%02X", pcore->host.Rx_Buffer[k]);
				}
				vcp_printf("\r\n");
			}
			else {
				dbg_printf(DBGMODE_ERR, "USBH_Get_HID_Descriptor_Blocking failed status: 0x%04X\r\n", status);
				USBH_ErrorHandle(pcore, pdev, status);
				continue;
			}

			uint8_t repIdList[8] = { 0, 0, 0, 0, 0, 0, 0, 0};

			status = USBH_Get_HID_ReportDescriptor_Blocking(pcore , pdev, i, hidDesc.wItemLength);
			if (status == USBH_OK) {
				dbg_printf(DBGMODE_DEBUG, "USBH_Get_HID_ReportDescriptor_Blocking OK: 0x%04X\r\n", status);

				vcp_printf("%sI%d:C%d:ReptDesc:", USBH_Dev_DebugPrint(pdev, 0), i, hidDesc.wItemLength);
				for (uint8_t k = 0; k < hidDesc.wItemLength; k++) {
					vcp_printf(" 0x%02X", pcore->host.Rx_Buffer[k]);
				}
				vcp_printf("\r\n");

				HID_Rpt_Parsing_Params_Reset(parser);
				HID_Rpt_Desc_Parse(pcore->host.Rx_Buffer, hidDesc.wItemLength, parser, parserEp, repIdList);
				//dbg_printf(DBGMODE_DEBUG, "HID_Rpt_Desc_Parse Complete \r\n");
				HID_Rpt_Parsing_Params_Debug_Dump(parser);
			}
			else {
				dbg_printf(DBGMODE_ERR, "USBH_Get_HID_ReportDescriptor_Blocking failed status: 0x%04X\r\n", status);
				USBH_ErrorHandle(pcore, pdev, status);
				continue;
			}

			char hasSetIdle = 0;
			for (int ridIdx = 0; ridIdx < 8; ridIdx++)
			{
				uint8_t rid = repIdList[ridIdx];
				if (rid > 0)
				{
					hasSetIdle = 1;
					status = USBH_Set_Idle_Blocking (pcore, pdev, i, 0, rid);
					if (status == USBH_OK) {
						dbg_printf(DBGMODE_DEBUG, "USBH_Set_Idle_Blocking[%d] OK: 0x%04X\r\n", rid, status);
					}
					else if(status == USBH_NOT_SUPPORTED || status == USBH_STALL) {
						dbg_printf(DBGMODE_DEBUG, "USBH_Set_Idle_Blocking[%d] NOT SUPPORTED\r\n", rid);
					}
					else {
						dbg_printf(DBGMODE_ERR, "USBH_Set_Idle_Blocking[%d] failed status: 0x%04X\r\n", rid, status);
						USBH_ErrorHandle(pcore, pdev, status);
					}
				}

				// end of list
				if (rid == 0) {
					break;
				}
			}

			if (hasSetIdle == 0)
			{
				status = USBH_Set_Idle_Blocking (pcore, pdev, i, 0, 0);
				if (status == USBH_OK) {
					dbg_printf(DBGMODE_DEBUG, "USBH_Set_Idle_Blocking[only %d] OK: 0x%04X\r\n", 0, status);
				}
				else if(status == USBH_NOT_SUPPORTED || status == USBH_STALL) {
					dbg_printf(DBGMODE_DEBUG, "USBH_Set_Idle_Blocking[only %d] NOT SUPPORTED\r\n", 0);
				}
				else {
					dbg_printf(DBGMODE_ERR, "USBH_Set_Idle_Blocking[only %d] failed status: 0x%04X\r\n", 0, status);
					USBH_ErrorHandle(pcore, pdev, status);
				}
			}
		}

		if (pdev->device_prop.Dev_Desc.idVendor == SONY_VID && pdev->device_prop.Dev_Desc.idProduct == DUALSHOCK4_PID)
		{
			// TODO
		}
		else
		{
			status = USBH_Set_Protocol_Blocking(pcore, pdev, i, 0); // this sets the protocol = "report"
			if (status == USBH_OK) {
				dbg_printf(DBGMODE_DEBUG, "USBH_Set_Protocol_Blocking OK: 0x%04X\r\n", status);
			}
			else {
				dbg_printf(DBGMODE_ERR, "USBH_Set_Protocol_Blocking failed status: 0x%04X\r\n", status);
				USBH_ErrorHandle(pcore, pdev, status);
			}
		}
	}

	if (isHid == 0) {

		// none of the interfaces are HID
		free(pdev->Usr_Data);
		pdev->Usr_Data = 0;
		pdev->cb = &USBH_Dev_CB_Default; // this will cause the device to not be serviced
	}

	if (HID_Data->init_handler != 0) {
		HID_Data->init_handler(pcore, pdev);
	}

	USBH_Dev_HID_Cnt++;
}
示例#5
0
void USBH_Dev_Hub_EnumerationDone(USB_OTG_CORE_HANDLE *pcore , USBH_DEV *pdev)
{
	dbg_printf(DBGMODE_TRACE, "Hub_EnumerationDone \r\n");

	if (pdev->Usr_Data != 0) {
		free(pdev->Usr_Data);
		pdev->Usr_Data = 0;
	}
	pdev->Usr_Data = calloc(1, sizeof(Hub_Data_t));
	Hub_Data_t* Hub_Data = pdev->Usr_Data;

	uint8_t maxEP = ( (pdev->device_prop.Itf_Desc[0].bNumEndpoints <= USBH_MAX_NUM_ENDPOINTS) ?
					pdev->device_prop.Itf_Desc[0].bNumEndpoints :
					USBH_MAX_NUM_ENDPOINTS);

	for (uint8_t num=0; num < maxEP; num++)
	{
		USBH_EpDesc_TypeDef* epDesc = &(pdev->device_prop.Ep_Desc[0][num]);

		if ((epDesc->bmAttributes & EP_TYPE_MSK) == USB_EP_TYPE_INTR && (epDesc->bEndpointAddress & USB_EP_DIR_MSK) == USB_EP_DIR_IN)
		{
			//if (epDesc->bInterval > 50) epDesc->bInterval = 50;

			Hub_Data->intInEpIo = USBH_DevIO_Manager_New(pcore, pdev, epDesc,
#ifdef HUB_ENABLE_DYNAMIC_HC_ALLOC
						1
#else
						0
#endif
						, USBH_Dev_Hub_DataHandler, 0);
			Hub_Data->intInEpIo->force_poll_interval = 1;
			Hub_Data->intInEpIo->timeout = 10;
		}
	}

	if (Hub_Data->intInEpIo == 0) {
		dbg_printf(DBGMODE_ERR, "Hub %s has no interrupt-in endpoints!\r\n", USBH_Dev_DebugPrint(pdev, 0));
	}

	// the old example HID code used a state machine to perform the sequence of requests, but here we will just do everything in a sequence

	// get the hub descriptor so we know the number of ports available
	USBH_Status status = USBH_GetDescriptor_Blocking(pcore,
								pdev,
								USB_REQ_RECIPIENT_DEVICE
								| USB_REQ_TYPE_CLASS,
								USB_DESC_HUB,
								0,
								pcore->host.Rx_Buffer,
								USB_HUB_DESC_SIZE
								);

	if (status != USBH_OK) {
		dbg_printf(DBGMODE_ERR, "Hub_EnumerationDone GetDescriptor failed, status 0x%02X \r\n", status);
		USBH_ErrorHandle(pcore, pdev, status);
		return;
	}

	Hub_Data->num_ports = pcore->host.Rx_Buffer[2];

	//dbg_printf(DBGMODE_DEBUG, "\tbDescriptorType = 0x%02X\r\n", pcore->host.Rx_Buffer[1]);
	dbg_printf(DBGMODE_DEBUG, "\tnum_ports = %d\r\n", Hub_Data->num_ports);
	vcp_printf("Hub V%04XP%04XA%d Enumerated, %d ports\r\n", pdev->device_prop.Dev_Desc.idVendor, pdev->device_prop.Dev_Desc.idProduct, pdev->device_prop.address, Hub_Data->num_ports);

	// allocate memory for the children devices
	if (Hub_Data->children != 0) {
		free(Hub_Data->children);
		Hub_Data->children = 0;
	}
	Hub_Data->children = calloc(Hub_Data->num_ports, sizeof(USBH_DEV*));

	// iterate all the ports
	for (int pn = 0; pn < Hub_Data->num_ports; pn++)
	{
		Hub_Data->children[pn] = 0; // reset

		uint16_t wps, wpc;

		status = USBH_Dev_Hub_GetPortStatus(pcore, pdev, pn, &wps, &wpc);
		if (status != USBH_OK) {
			dbg_printf(DBGMODE_ERR, "Hub_EnumerationDone GetPortStatus (pn %d) failed, status 0x%02X \r\n", pn + 1, status);
			USBH_ErrorHandle(pcore, pdev, status);
			continue;
		}

		status = USBH_Dev_Hub_SetPortFeature(pcore, pdev, pn, HUBREQ_PORT_POWER);
		if (status != USBH_OK) {
			dbg_printf(DBGMODE_ERR, "Hub_EnumerationDone SetPortFeature (pn %d) failed, status 0x%02X \r\n", pn + 1, status);
			USBH_ErrorHandle(pcore, pdev, status);
			continue;
		}
	}

	// wait for power ready
	char pwrRdy;
	volatile int pwrTries = 700 / Hub_Data->num_ports;
	do
	{
		pwrRdy = 1;
		for (int pn = 0; pn < Hub_Data->num_ports; pn++)
		{
			uint16_t wps, wpc;

			status = USBH_Dev_Hub_GetPortStatus(pcore, pdev, pn, &wps, &wpc);
			if (status != USBH_OK) {
				dbg_printf(DBGMODE_ERR, "Hub_EnumerationDone GetPortStatus (pn %d) failed, status 0x%02X \r\n", pn + 1, status);
				//USBH_ErrorHandle(pcore, pdev, status);
				continue;
			}

			if (wps & (1 << HUBWPORTSTATUS_POWER_BIT) == 0) {
				pwrRdy = 0;
			}
		}
	}
	while (pwrRdy == 0 && pwrTries--);

	if (pwrRdy != 0) {
		dbg_printf(DBGMODE_TRACE, "Hub_EnumerationDone all port power ready \r\n");
	}
	else {
		dbg_printf(DBGMODE_ERR, "Hub_EnumerationDone error, power not ready \r\n");
	}

	vcp_printf("%s:Hub Ready, Ports: %d \r\n", USBH_Dev_DebugPrint(pdev, 0), Hub_Data->num_ports);
}
示例#6
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)) 
  {
  	 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;
  }

}