Example #1
0
/**
 * This function will initialize susb host controller device.
 *
 * @param dev the host controller device to be initalize.
 * 
 * @return the error code, RT_EOK on successfully.
 */
static rt_err_t susb_init(rt_device_t dev)
{    
    rt_sem_init(&sem_lock, "s_lock", 1, RT_IPC_FLAG_FIFO);    

    /* roothub initilizition */
    root_hub.num_ports = 1;
    root_hub.is_roothub = RT_TRUE;
    root_hub.self = RT_NULL;
    root_hub.hcd = &susb_hcd;

    /* Hardware Init */
    USB_OTG_BSP_Init(&USB_OTG_Core);  
    
    /* configure GPIO pin used for switching VBUS power */
    USB_OTG_BSP_ConfigVBUS(0);    
    
    /* Host de-initializations */
    USBH_DeInit(&USB_OTG_Core, &USB_Host);
    
    /* Start the USB OTG core */     
    HCD_Init(&USB_OTG_Core , USB_OTG_FS_CORE_ID);

    USBH_DeAllocate_AllChannel(&USB_OTG_Core);  
          
    /* Enable Interrupts */
    USB_OTG_BSP_EnableInterrupt(&USB_OTG_Core);    

    return RT_EOK;
}
Example #2
0
/**
  * @brief  USBH_Init
  *         Host hardware and stack initializations
  * @param  class_cb: Class callback structure address
  * @param  usr_cb: User callback structure address
  * @retval None
  */
void USBH_Init(USB_OTG_CORE_HANDLE *pdev,
               USB_OTG_CORE_ID_TypeDef coreID,
               USBH_HOST *phost,
               USBH_Class_cb_TypeDef *class_cb,
               USBH_Usr_cb_TypeDef *usr_cb)
{

  /* Hardware Init */
  USB_OTG_BSP_Init(pdev);

  /* configure GPIO pin used for switching VBUS power */
  USB_OTG_BSP_ConfigVBUS(0);


  /* Host de-initializations */
  USBH_DeInit(pdev, phost);

  /*Register class and user callbacks */
  phost->class_cb = class_cb;
  phost->usr_cb = usr_cb;

  /* Start the USB OTG core */
   HCD_Init(pdev , coreID);

  /* Upon Init call usr call back */
  phost->usr_cb->Init();

  /* Enable Interrupts */
  USB_OTG_BSP_EnableInterrupt(pdev);
}
TM_USB_MSCHOST_Result_t TM_USB_MSCHOST_DeInit(void) {
	/* Deinit USB host */
	USBH_DeInit(&USB_OTG_MSC_Core, &USB_Host);
	
	/* Return OK */
	return TM_USB_MSCHOST_Result_Disconnected;
}
Example #4
0
/**
  * @brief  USBH_Disconnect
  *         USB Disconnect callback function from the Interrupt. 
  * @param  selected device
  * @retval none
  */
rt_uint8_t susb_disconnect (USB_OTG_CORE_HANDLE *pdev)
{    
    struct uhost_msg msg;

    pdev->host.ConnSts = 0;

    rt_kprintf("susb_disconnect\n");

    USBH_DeInit(&USB_OTG_Core , &USB_Host);
    USBH_DeAllocate_AllChannel(&USB_OTG_Core);  
    USB_Host.gState = HOST_IDLE;

    root_hub.port_status[0] |= PORT_CCSC;
    root_hub.port_status[0] &= ~PORT_CCS;
    msg.type = USB_MSG_CONNECT_CHANGE;
    msg.content.uhub = &root_hub;
    rt_usb_post_event(&msg, sizeof(struct uhost_msg));    

    return 0;
}
Example #5
0
void USBH_Dev_Hub_DeviceDisconnected(USB_OTG_CORE_HANDLE *pcore , USBH_DEV *pdev)
{
	dbg_printf(DBGMODE_TRACE, "USBH_Dev_Hub_DeviceDisconnected\r\n");

	Hub_Data_t* Hub_Data = pdev->Usr_Data;
	// iterate all the ports
	for (int pn = 0; pn < Hub_Data->num_ports && Hub_Data->children != 0; pn++)
	{
		if (Hub_Data->children[pn] != 0) {
			// disconnect event for all children
			((USBH_Device_cb_TypeDef*)Hub_Data->children[pn]->cb)->DeviceDisconnected(pcore, pdev);
			USBH_DeInit(pcore, Hub_Data->children[pn]); // frees channels
			((USBH_Device_cb_TypeDef*)Hub_Data->children[pn]->cb)->DeInit(pcore, Hub_Data->children[pn]);
			((USBH_Device_cb_TypeDef*)Hub_Data->children[pn]->cb)->DeInitDev(pcore, Hub_Data->children[pn]); // this is the one that frees memory
			//free(Hub_Data->children[pn]);
			Hub_Data->children[pn] = 0;
		}
	}

	if (Hub_Data->children != 0) {
		free(Hub_Data->children);
		Hub_Data->children = 0;
	}
}
Example #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))
  {
    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;
  }

}
Example #7
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;
  }

}
Example #9
0
void USBH_Dev_Hub_DataHandler(void* p_io, uint8_t* data, uint16_t len)
{
	USBH_DevIO_t* p_in = p_io;
	USBH_DEV* pdev = p_in->pdev;
	USB_OTG_CORE_HANDLE* pcore = p_in->pcore;
	Hub_Data_t* Hub_Data = pdev->Usr_Data;
	USBH_Status errCode;

	int8_t alloc = 0;
	USBH_Dev_AllocControl(pcore, pdev);

	// when a device connects or disconnects from the hub, the hub will issue an interrupt-in message

	// iterate all the ports
	for (int pn = 0; pn < Hub_Data->num_ports; pn++)
	{
		int pnp1 = pn + 1;
		uint8_t bitIdx = pnp1 % 8;
		uint8_t byteIdx = pnp1 / 8;
		// did this port cause the event?
		if (data[byteIdx] & (1 << bitIdx))
		{
			if (Hub_Data->port_busy != 0 && Hub_Data->port_busy != pnp1) {
				// we can only handle one new device at a time, or else they all listen to address 0
				continue;
			}

			if (alloc == 0) {
				alloc = USBH_Dev_AllocControl(p_in->pcore, p_in->pdev);
			}

			uint16_t wPortStatus, wPortChange;
			errCode = USBH_Dev_Hub_GetPortStatus(pcore, pdev, pn, &wPortStatus, &wPortChange);

			if (errCode != USBH_OK) {
				dbg_printf(DBGMODE_ERR, "USBH_Dev_Hub_Handle_InterruptIn GetPortStatus (pn %d) failed (status 0x%04X) \r\n", pn, errCode);
				if (errCode == USBH_STALL || errCode == USBH_NOT_SUPPORTED) {
					errCode = USBH_ClrFeature_Blocking(pcore, pdev, 0, 0);
				}
				continue;
			}

			dbg_printf(DBGMODE_DEBUG, "Hub_Handle_InterruptIn Hub_GetPortStatus, pn: %d, s: 0x%04X, c: 0x%04X\r\n", pnp1, wPortStatus, wPortChange);

			if ((wPortStatus & (1 << HUBWPORTSTATUS_POWER_BIT)) == 0) {
				errCode = USBH_Dev_Hub_SetPortFeature(pcore, pdev, pnp1, HUBREQ_PORT_POWER);
				if (errCode == USBH_STALL || errCode == USBH_NOT_SUPPORTED) {
					errCode = USBH_ClrFeature_Blocking(pcore, pdev, 0, 0);
				}
			}

			if ((wPortStatus & (1 << HUBWPORTCHANGE_ENABLED_BIT)) == 0) {
				errCode = USBH_Dev_Hub_SetPortFeature(pcore, pdev, pn, HUBREQ_PORT_ENABLE);
				if (errCode == USBH_STALL || errCode == USBH_NOT_SUPPORTED) {
					errCode = USBH_ClrFeature_Blocking(pcore, pdev, 0, 0);
				}
			}

			if ((wPortChange & (1 << HUBWPORTCHANGE_RESET_BIT)) != 0) {
				errCode = USBH_Dev_Hub_ClearPortFeature(pcore, pdev, pn, HUBREQ_C_PORT_RESET, 0);
				if (errCode == USBH_STALL || errCode == USBH_NOT_SUPPORTED) {
					errCode = USBH_ClrFeature_Blocking(pcore, pdev, 0, 0);
				}
			}

			if ((wPortChange & (1 << HUBWPORTCHANGE_CONNSTAT_BIT)) != 0) {
				errCode = USBH_Dev_Hub_ClearPortFeature(pcore, pdev, pn, HUBREQ_C_PORT_CONNECTION, 0);
				if (errCode == USBH_STALL || errCode == USBH_NOT_SUPPORTED) {
					errCode = USBH_ClrFeature_Blocking(pcore, pdev, 0, 0);
				}
			}

			if ((wPortChange & (1 << HUBWPORTCHANGE_ENABLED_BIT)) != 0) {
				errCode = USBH_Dev_Hub_ClearPortFeature(pcore, pdev, pn, HUBREQ_C_PORT_ENABLE, 0);
				if (errCode == USBH_STALL || errCode == USBH_NOT_SUPPORTED) {
					errCode = USBH_ClrFeature_Blocking(pcore, pdev, 0, 0);
				}
			}

			if ((wPortStatus & (1 << HUBWPORTSTATUS_RESET_BIT)) != 0)
			{
				if (Hub_Data->children[pn] != 0 && Hub_Data->children[pn]->gState == HOST_IDLE)
				{
					Hub_Data->children[pn]->gState = HOST_DEV_RESET_PENDING;
				}
			}
			else
			{
				if (((wPortStatus & (1 << HUBWPORTSTATUS_CURCONN_BIT)) == 0 ||
				     (wPortStatus & (1 << HUBWPORTSTATUS_ENABLED_BIT)) == 0) &&
				     Hub_Data->children[pn] != 0 && Hub_Data->children[pn]->cb != 0 &&
				     Hub_Data->children[pn]->gState != HOST_IDLE && Hub_Data->children[pn]->gState != HOST_DEV_RESET_PENDING)
				{
					dbg_printf(DBGMODE_TRACE, "Hub %s disconnected device (pn %d)\r\n", USBH_Dev_DebugPrint(pdev, 0), pnp1);
					vcp_printf("Hub %s Lost Device on Port %d\r\n", USBH_Dev_DebugPrint(pdev, 0), pnp1);

					((USBH_Device_cb_TypeDef*)Hub_Data->children[pn]->cb)->DeviceDisconnected(pcore, pdev);
					USBH_DeInit(pcore, Hub_Data->children[pn]); // frees channels
					((USBH_Device_cb_TypeDef*)Hub_Data->children[pn]->cb)->DeInit(pcore, Hub_Data->children[pn]);
					((USBH_Device_cb_TypeDef*)Hub_Data->children[pn]->cb)->DeInitDev(pcore, Hub_Data->children[pn]); // this is the one that frees memory
					free(Hub_Data->children[pn]);
					Hub_Data->children[pn] = 0;
				}
				else if ((wPortStatus & (1 << HUBWPORTSTATUS_CURCONN_BIT)) != 0)
				{
					if ((wPortStatus & (1 << HUBWPORTSTATUS_RESET_BIT)) == 0 &&
					    (wPortStatus & (1 << HUBWPORTSTATUS_ENABLED_BIT)) != 0 &&
						Hub_Data->children[pn] != 0 && Hub_Data->children[pn]->cb != 0 && (Hub_Data->children[pn]->gState == HOST_DEV_RESET_PENDING || Hub_Data->children[pn]->gState == HOST_IDLE))
					{
						if (((USBH_Device_cb_TypeDef*)Hub_Data->children[pn]->cb)->ResetDevice != 0)
							((USBH_Device_cb_TypeDef*)Hub_Data->children[pn]->cb)->ResetDevice(pcore, pdev);
						Hub_Data->children[pn]->device_prop.speed = (wPortStatus & (1 << 9)) ? HPRT0_PRTSPD_LOW_SPEED : HPRT0_PRTSPD_FULL_SPEED; // if bit 9 is 1, then it is low speed (0x02), or else it is full speed (0x01)
						if (((USBH_Device_cb_TypeDef*)Hub_Data->children[pn]->cb)->DeviceSpeedDetected != 0)
							((USBH_Device_cb_TypeDef*)Hub_Data->children[pn]->cb)->DeviceSpeedDetected(pcore, Hub_Data->children[pn], Hub_Data->children[pn]->device_prop.speed);

						Hub_Data->children[pn]->gState = HOST_DEV_DELAY;
						USBH_Dev_Reset_Timer = systick_1ms_cnt;
						Hub_Data->children[pn]->device_prop.address = 0; // new attached devices to a hub is always address 0
						Hub_Data->port_busy = pnp1;
						Hub_Data->intInEpIo->enabled = 0;
						// we are allowed to pass this on to the upper state machine now, it will seem like it was attached normally
						dbg_printf(DBGMODE_TRACE, "Hub passed new device (pn %d) to upper state machine \r\n", pnp1);
						vcp_printf("Hub %s New Device on Port %d\r\n", USBH_Dev_DebugPrint(pdev, 0), pnp1);
					}
					else if (Hub_Data->children[pn] == 0)
					{
						errCode = USBH_Dev_Hub_SetPortFeature(pcore, pdev, pn, HUBREQ_PORT_RESET);
						Hub_Data->children[pn] = calloc(1, sizeof(USBH_DEV));
						Hub_Data->children[pn]->Parent = pdev;
						Hub_Data->children[pn]->gState = HOST_IDLE;
						Hub_Data->children[pn]->gStateBkp = HOST_IDLE;
						Hub_Data->children[pn]->EnumState = ENUM_IDLE;
						Hub_Data->children[pn]->RequestState = CMD_SEND;
						Hub_Data->children[pn]->device_prop.address = USBH_DEVICE_ADDRESS_DEFAULT; // this better be 0
						Hub_Data->children[pn]->device_prop.speed = HPRT0_PRTSPD_LOW_SPEED;
						Hub_Data->children[pn]->port_num = pnp1;
						Hub_Data->children[pn]->Control.hc_num_in = -1;
						Hub_Data->children[pn]->Control.hc_num_out = -1;
						Hub_Data->children[pn]->Control.hc_in_tgl_in = -1;
						Hub_Data->children[pn]->Control.hc_in_tgl_out = -1;
						Hub_Data->children[pn]->Control.hc_out_tgl_in = -1;
						Hub_Data->children[pn]->Control.hc_out_tgl_out = -1;
						Hub_Data->children[pn]->Control.state = CTRL_IDLE;
						Hub_Data->children[pn]->Control.ep0size = USB_OTG_MAX_EP0_SIZE;
						Hub_Data->children[pn]->cb = (void*)&USBH_Dev_CB_Default;
						Hub_Data->port_busy = pnp1;
						dbg_printf(DBGMODE_TRACE, "Hub %s created new child (pn %d) \r\n", USBH_Dev_DebugPrint(pdev, 0), pnp1);
					}
				}
			}
		}
	}

	if (alloc != 0) {
		USBH_Dev_FreeControl(p_in->pcore, p_in->pdev);
	}
}
Example #10
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;
  }

}