Beispiel #1
0
/**
* @brief  USBH_HID_Handle 
*         The function is for managing state machine for HID data transfers 
* @param  pdev: Selected device
* @param  hdev: Selected device property
* @retval USBH_Status
*/
static USBH_Status USBH_HID_Handle(USB_OTG_CORE_HANDLE *pdev , 
                                   void   *phost)
{
  USBH_HOST *pphost = phost;
  USBH_Status status = USBH_OK;
  
  switch (HID_Machine.state)
  {
    
  case HID_IDLE:
    HID_Machine.cb->Init();
    HID_Machine.state = HID_SYNC;
    
  case HID_SYNC:

    /* Sync with start of Even Frame */
    if(USB_OTG_IsEvenFrame(pdev) == TRUE)
    {
      HID_Machine.state = HID_GET_DATA;  
    }
    break;
    
  case HID_GET_DATA:

    USBH_InterruptReceiveData(pdev, 
                              HID_Machine.buff,
                              HID_Machine.length,
                              HID_Machine.hc_num_in);
    start_toggle = 1;
    
    HID_Machine.state = HID_POLL;
    HID_Machine.timer = HCD_GetCurrentFrame(pdev);
    break;
    
  case HID_POLL:
    if(( HCD_GetCurrentFrame(pdev) - HID_Machine.timer) >= HID_Machine.poll)
    {
      HID_Machine.state = HID_GET_DATA;
    }
    else if(HCD_GetURB_State(pdev , HID_Machine.hc_num_in) == URB_DONE)
    {
      if(start_toggle == 1) /* handle data once */
      {
        start_toggle = 0;
        HID_Machine.cb->Decode(HID_Machine.buff);
      }
    }
    else if(HCD_GetURB_State(pdev, HID_Machine.hc_num_in) == URB_STALL) /* IN Endpoint Stalled */
    {
      
      /* Issue Clear Feature on interrupt IN endpoint */ 
      if( (USBH_ClrFeature(pdev, 
                           pphost,
                           HID_Machine.ep_addr,
                           HID_Machine.hc_num_in)) == USBH_OK)
      {
        /* Change state to issue next IN token */
        HID_Machine.state = HID_GET_DATA;
        
      }
      
    }      
    break;
    
  default:
    break;
  }
  return status;
}
Beispiel #2
0
/**
  * @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 transfered 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;
    }
    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.status = CTRL_STALL;
      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;
}
Beispiel #3
0
/**
* @brief  USBH_HID_Handle 
*         The function is for managing state machine for HID data transfers 
* @param  pdev: Selected device
* @param  hdev: Selected device property
* @retval USBH_Status
*/
static USBH_Status USBH_HID_Handle(USB_OTG_CORE_HANDLE *pdev , 
                                   void   *phost)
{
  USBH_HOST *pphost = phost;
  HID_Machine_TypeDef *HID_Machine = &HID_Machines[pdev->cfg.coreID];
  USBH_Status status = USBH_OK;
  
  switch (HID_Machine->state)
  {
    
  case HID_IDLE:
    HID_Machine->cb->Init(pdev->cfg.coreID,pphost->device_prop.Dev_Desc.idVendor,pphost->device_prop.Dev_Desc.idProduct);
    HID_Machine->state = HID_SYNC;
    
  case HID_SYNC:

    /* Sync with start of Even Frame */
    if(USB_OTG_IsEvenFrame(pdev) == TRUE)
    {
      HID_Machine->state = HID_GET_DATA;  
    }
    break;
    
  case HID_GET_DATA:

    USBH_InterruptReceiveData(pdev, 
                              HID_Machine->buff,
                              HID_Machine->length,
                              HID_Machine->hc_num_in);
    start_toggles[pdev->cfg.coreID] = 1;
    
    HID_Machine->state = HID_POLL;
    HID_Machine->timer = HCD_GetCurrentFrame(pdev);
    break;
    
  case HID_POLL:
    if(( HCD_GetCurrentFrame(pdev) - HID_Machine->timer) >= HID_Machine->poll)
    {
      HID_Machine->state = HID_GET_DATA;
    }
    else if(HCD_GetURB_State(pdev , HID_Machine->hc_num_in) == URB_DONE)
    {
      if(start_toggles[pdev->cfg.coreID] == 1) /* handle data once */
      {
        start_toggles[pdev->cfg.coreID] = 0;
        HID_Machine->cb->Decode(pdev->cfg.coreID,HID_Machine->buff);
      }
    }
    else if(HCD_GetURB_State(pdev, HID_Machine->hc_num_in) == URB_STALL) /* IN Endpoint Stalled */
    {
      
      /* Issue Clear Feature on interrupt IN endpoint */ 
      if( (USBH_ClrFeature(pdev, 
                           pphost,
                           HID_Machine->ep_addr,
                           HID_Machine->hc_num_in)) == USBH_OK)
      {
        /* Change state to issue next IN token */
        HID_Machine->state = HID_GET_DATA;
        
      }
      
    }      
    break;
    
  default:
    break;
  }
  return status;
}
Beispiel #4
0
uint8_t USBPTD_SetupStage(USB_OTG_CORE_HANDLE* pcore, USB_SETUP_REQ* req)
{
	// store for later use from another function
	memcpy(USBPT_LastSetupPacket, pcore->dev.setup_packet, 24);

	// print for monitoring
	USBPT_printf("\b\r\n USBPT:SETUP:");
	for (uint8_t i = 0; i < 8; i++) {
		USBPT_printf(" 0x%02X", USBPT_LastSetupPacket[i]);
	}
	USBPT_printf("\r\n");

	// prepare to be sent to the device
	memcpy(USBPT_Dev->Control.setup.d8, USBPT_LastSetupPacket, 8);

	// set address must be handled explicitly
	if ((req->bmRequest & 0x7F) == (USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD) && req->bRequest == USB_REQ_SET_ADDRESS)
	{
		// let the internal code handle it for the device interface
		USBD_StdDevReq(pcore, req);

		// pass it to the downstream device
		USBH_CtlReq_Blocking(&USB_OTG_Core_host, USBPT_Dev, 0, 0, 100);
		USBD_CtlSendStatus(pcore);

		// modifiy our host channel to match
		USBPT_Dev->device_prop.address = (uint8_t)(req->wValue) & 0x7F;
		USBH_Modify_Channel (&USB_OTG_Core_host,
							USBPT_Dev->Control.hc_num_in,
							USBPT_Dev->device_prop.address,
							0,
							0,
							0);
		USBH_Modify_Channel (&USB_OTG_Core_host,
							USBPT_Dev->Control.hc_num_out,
							USBPT_Dev->device_prop.address,
							0,
							0,
							0);

		// modify all other channels to match
		for (uint8_t i = 0; i < USBPTH_MAX_LISTENERS; i++)
		{
			USBPTH_HC_EP_t* pl = &USBPTH_Listeners[i];
			uint8_t hc = pl->hc;
			if (hc != 0 && hc != HC_ERROR) // if listener is actually allocated
			{
				USBH_EpDesc_TypeDef* epDesc = pl->epDesc;
				uint8_t epType = 0;
				if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_INTR) {
					epType = EP_TYPE_INTR;
				}
				else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_BULK) {
					epType = EP_TYPE_BULK;
				}
				else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_ISOC) {
					epType = EP_TYPE_ISOC;
				}
				else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_CTRL) {
					epType = EP_TYPE_CTRL;
				}

				USBH_Modify_Channel(	&USB_OTG_Core_host,
										USBPTH_Listeners[i].hc,
										USBPT_Dev->device_prop.address,
										USBPT_Dev->device_prop.speed,
										epType,
										USBPTH_Listeners[i].epDesc->wMaxPacketSize);
			}
		}
		// note: out direction channels are dynamically allocated only when needed
		// so we don't need to modify those channel addresses

		return USBD_OK;
	}

	// no data means we can just directly relay the data
	if (req->wLength == 0) {
		USBH_CtlReq_Blocking(&USB_OTG_Core_host, USBPT_Dev, 0, 0, 100);
		USBD_CtlSendStatus(pcore);
		return USBD_OK;
	}

	// there is extra data later
	USBPT_CtrlDataLen = req->wLength;
	if (USBPT_CtrlData != 0) free(USBPT_CtrlData);
	USBPT_CtrlData = malloc(USBPT_CtrlDataLen);

	USBH_Status status;

	// wait until previous req is finished
	delay_1ms_cnt = 100;
	while (delay_1ms_cnt > 0 &&
			USBPT_Dev->Control.state != CTRL_COMPLETE &&
			USBPT_Dev->Control.state != CTRL_IDLE &&
			USBPT_Dev->Control.state != CTRL_ERROR &&
			USBPT_Dev->Control.state != CTRL_STALLED);
	{
		status = USBH_HandleControl(&USB_OTG_Core_host, USBPT_Dev);
	}

	// finalize previous ctrl req
	if (USBPT_Dev->RequestState == CMD_WAIT) {
		USBH_CtlReq(&USB_OTG_Core_host, USBPT_Dev, 0 , 0 );
	}

	// prepare new setup
	USBH_SubmitSetupRequest(USBPT_Dev, USBPT_CtrlData, USBPT_CtrlDataLen);
	USBPT_Dev->RequestState = CMD_WAIT;
	USBH_CtlSendSetup (&USB_OTG_Core_host, USBPT_Dev->Control.setup.d8, USBPT_Dev->Control.hc_num_out);
	USBPT_Dev->Control.state = CTRL_SETUP_WAIT;
	USBPT_Dev->Control.timer = HCD_GetCurrentFrame(pcore);
	USBPT_Dev->Control.timeout = 50;

	if ((req->bmRequest & 0x80) == 0)
	{ // H2D
		// we need to obtain the data from EP0_RxReady first
		USBD_CtlPrepareRx (pcore, USBPT_CtrlData, USBPT_CtrlDataLen);
		return USBD_OK;
	}
	else
	{ // D2H

		// wait for request to finish
		delay_1ms_cnt = 100;
		do
		{
			status = USBH_CtlReq(&USB_OTG_Core_host, USBPT_Dev, USBPT_CtrlData , USBPT_CtrlDataLen );
			if (status == USBH_OK || status == USBH_FAIL || status == USBH_STALL || status == USBH_NOT_SUPPORTED) {
				break;
			}
			else
			{
				status = USBH_HandleControl(&USB_OTG_Core_host, USBPT_Dev);
				if (status == USBH_FAIL || status == USBH_STALL || status == USBH_NOT_SUPPORTED) {
					break;
				}
			}
		}
		while (delay_1ms_cnt > 0);

		if (delay_1ms_cnt == 0)
		{
			// timeout
			dbg_printf(DBGMODE_ERR, "USBPT Setup Timed Out \r\n");
			USBD_CtlSendStatus(pcore); // we reply with nothing to simulate a timeout
			return USBH_OK;
		}
		else if (status == USBH_OK)
		{
			// all good, send back the data
			USBD_CtlSendData (pcore, USBPT_CtrlData, USBPT_CtrlDataLen);

			// handle config descriptors specially, we need to know what channels to open based on endpoints
			if ((req->bmRequest & 0x7F) == (USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD) &&
					req->bRequest == USB_REQ_GET_DESCRIPTOR &&
					req->wValue == USB_DESC_CONFIGURATION &&
					req->wLength > USB_CONFIGURATION_DESC_SIZE)
			{
				// this is a full length configuration descriptor
				// we need this info to open as many D2H endpoints to channels
				USBH_ParseCfgDesc(&USBPT_Dev->device_prop.Cfg_Desc,
									USBPT_Dev->device_prop.Itf_Desc,
									USBPT_Dev->device_prop.Ep_Desc,
									USBPT_CtrlData,
									USBPT_CtrlDataLen);

				USBPTH_OutEPCnt = 0;
				USBPT_GeneralInDataLen = 0;
				for (uint8_t i = 0; i < USBPT_Dev->device_prop.Cfg_Desc.bNumInterfaces && i < USBH_MAX_NUM_INTERFACES; i++)
				{
					for (uint8_t j = 0; j < USBPT_Dev->device_prop.Itf_Desc[i].bNumEndpoints && j < USBH_MAX_NUM_ENDPOINTS; j++)
					{
						USBH_EpDesc_TypeDef* epDesc = &USBPT_Dev->device_prop.Ep_Desc[i][j];
						for (uint8_t k = 0; k < USBPTH_MAX_LISTENERS; k++)
						{
							if ((epDesc->bEndpointAddress & USB_EP_DIR_MSK) == USB_D2H && USBPTH_Listeners[k].used == 0)
							{
								USBPTH_Listeners[k].epDesc = epDesc;
								uint8_t epType = 0;
								if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_INTR) {
									epType = EP_TYPE_INTR;
								}
								else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_BULK) {
									epType = EP_TYPE_BULK;
								}
								else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_ISOC) {
									epType = EP_TYPE_ISOC;
								}
								else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_CTRL) {
									epType = EP_TYPE_CTRL;
								}

								USBH_Open_Channel(	&USB_OTG_Core_host,
													&(USBPTH_Listeners[k].hc),
													epDesc->bEndpointAddress,
													USBPT_Dev->device_prop.address,
													USBPT_Dev->device_prop.speed,
													epType,
													USBPTH_Listeners[k].epDesc->wMaxPacketSize);

								if (USBPTH_Listeners[k].hc >= 0)
								{
									USBPTH_Listeners[k].used = 1;
									DCD_EP_Open(&USB_OTG_Core_dev, epDesc->bEndpointAddress, epDesc->wMaxPacketSize, epType);

									if (epDesc->wMaxPacketSize > USBPT_GeneralInDataMax) {
										USBPT_GeneralInDataMax = epDesc->wMaxPacketSize;
									}
								}
							}
						}

						if ((epDesc->bEndpointAddress & 0x80) == USB_H2D)
						{
							USBPTH_OutEPCnt++;
						}
					}
				}

				if (USBPT_GeneralInData != 0) free(USBPT_GeneralInData); // release memory if previously allocated
				USBPT_GeneralInData = malloc(USBPT_GeneralInDataMax); // only allocate the memory we need

				if (USBPTH_OutEP != 0) free(USBPTH_OutEP); // release memory if previously allocated
				USBPTH_OutEP = malloc(sizeof(USBH_EpDesc_TypeDef*) * USBPTH_OutEPCnt); // only allocate the memory we need

				uint8_t ec = 0;
				for (uint8_t i = 0; i < USBPT_Dev->device_prop.Cfg_Desc.bNumInterfaces && i < USBH_MAX_NUM_INTERFACES; i++)
				{
					for (uint8_t j = 0; j < USBPT_Dev->device_prop.Itf_Desc[i].bNumEndpoints && j < USBH_MAX_NUM_ENDPOINTS; j++)
					{
						USBH_EpDesc_TypeDef* epDesc = &USBPT_Dev->device_prop.Ep_Desc[i][j];
						if ((epDesc->bEndpointAddress & 0x80) == USB_H2D) {
							// only save the H2D direction endpoints
							USBPTH_OutEP[ec] = epDesc;
							ec++;
						}
					}
				}
			}
			return USBH_OK;
		}
		else
		{
			if (status == USBH_STALL || status == USBH_NOT_SUPPORTED) {
				dbg_printf(DBGMODE_ERR, "USBPT Setup Stalled \r\n");
				USBD_CtlError(pcore , req);
				return USBH_OK;
			}
		}

		return USBD_OK;
	}

	dbg_printf(DBGMODE_ERR, "USBPT Setup Unhandled Error \r\n");
	USBD_CtlError(pcore , req);

	return USBD_OK;
}
Beispiel #5
0
static int _usb_ctrl_request_handle(USB_OTG_CORE_HANDLE *pdev , 
                                    USBH_HOST *phost, 
                                    wifi_usb_adapter_t *adapter)
{
    wifi_usb_ctrl_request_t *ctl_req = &adapter->usb_ctrl_req;
    unsigned char direction;  
    static unsigned short timeout = 0;
    URB_STATE URB_Status = URB_IDLE;
    int status = 1;

    phost->Control.status = CTRL_START;

    switch (ctl_req->state) {
    case CTRL_IDLE:
        status = 0; /* indicate the state machine could be blocked */
        break;
        
    case CTRL_SETUP:
        /* Send a SETUP packet. */
        pdev->host.hc[ctl_req->hc_num_out].toggle_out = 0; 
        USBH_CtlSendSetup(pdev, ctl_req->ctrlreq.d8, ctl_req->hc_num_out);  
        ctl_req->state = CTRL_SETUP_WAIT;  
        break; 

    case CTRL_SETUP_WAIT:
        URB_Status = HCD_GetURB_State(pdev , ctl_req->hc_num_out); 
        ctl_req->status = URB_Status;
        if (URB_Status == URB_DONE) { 
            direction = (ctl_req->ctrlreq.b.bmRequestType & USB_REQ_DIR_MASK);

            /* check if there is a data stage. */
            if (ctl_req->ctrlreq.b.wLength.w != 0) {        
                timeout = CTRL_DATA_STAGE_TIMEOUT;
                if (direction == USB_D2H) {
                    /* Data Direction is IN. */
                    ctl_req->state = CTRL_DATA_IN;
                }
                else {
                    /* Data Direction is OUT. */
                    ctl_req->state = CTRL_DATA_OUT;

                } 
            }
            /* No DATA stage. */
            else {
                timeout = CTRL_NODATA_STAGE_TIMEOUT;

                /* If there is No Data Transfer Stage. */
                if (direction == USB_D2H) {
                    /* Data Direction is IN. */
                    ctl_req->state = CTRL_STATUS_OUT;

                }
                else {
                    /* Data Direction is OUT. */
                    ctl_req->state = CTRL_STATUS_IN;
                } 
            }
            
            /* Set the delay timer to enable timeout for data stage completion. */
            ctl_req->timer = HCD_GetCurrentFrame(pdev);
        }
        else if (URB_Status == URB_ERROR) {
            ctl_req->state = CTRL_ERROR;  
            /* To be add. */
        }    
        break;

    case CTRL_DATA_IN:  
        /* Issue an IN token. */ 
        USBH_CtlReceiveData(pdev,
                            ctl_req->buffer, 
                            ctl_req->length,
                            ctl_req->hc_num_in);

        ctl_req->state = CTRL_DATA_IN_WAIT;
        break;    

    case CTRL_DATA_IN_WAIT:
        USB_OTG_BSP_uDelay(200);

        URB_Status = HCD_GetURB_State(pdev , ctl_req->hc_num_in); 
        ctl_req->status = URB_Status;

        /* check is DATA packet transfered successfully. */
        if (URB_Status == URB_DONE) { 
            ctl_req->state = CTRL_STATUS_OUT;
        }
        
        /* manage error cases. */
        else if (URB_Status == URB_STALL) { 
            ctl_req->state =  CTRL_ERROR;
        }   
        else if (URB_Status == URB_ERROR) {
            /* Device error. */
            ctl_req->state = CTRL_ERROR;    
        }

        break;

    case CTRL_DATA_OUT:
        /* Start DATA out transfer (only one DATA packet). */
        USB_OTG_BSP_uDelay(200);
        pdev->host.hc[ctl_req->hc_num_out].toggle_out ^= 1; 

        USBH_CtlSendData(pdev,
                        ctl_req->buffer, 
                        ctl_req->length , 
                        ctl_req->hc_num_out);

        ctl_req->state = CTRL_DATA_OUT_WAIT;
        break;

    case CTRL_DATA_OUT_WAIT:
        URB_Status = HCD_GetURB_State(pdev, ctl_req->hc_num_out);
        ctl_req->status = URB_Status;
        
        if (URB_Status == URB_DONE) { 
            /* If the Setup Pkt is sent successful, then change the state. */
            ctl_req->state = CTRL_STATUS_IN;
        }

        /* handle error cases. */
        else if (URB_Status == URB_STALL) { 
            ctl_req->state = CTRL_ERROR;
        } 
        else if (URB_Status == URB_NOTREADY) { 
            /* Nack received from device. */
            ctl_req->state = CTRL_DATA_OUT;
        }    
        else if (URB_Status == URB_ERROR) {
            /* device error */
            ctl_req->state = CTRL_ERROR;   
        } 
        break;


    case CTRL_STATUS_IN:
        /* Send 0 bytes out packet. */
        USB_OTG_BSP_uDelay(200);
        USBH_CtlReceiveData(pdev,
                            0,
                            0,
                            ctl_req->hc_num_in);

        ctl_req->state = CTRL_STATUS_IN_WAIT;

        break;

    case CTRL_STATUS_IN_WAIT:
        URB_Status = HCD_GetURB_State(pdev, ctl_req->hc_num_in); 
        ctl_req->status = URB_Status;

        if (URB_Status == URB_DONE) { 
            /* Control transfers completed, Exit the State Machine */
            ctl_req->state = CTRL_IDLE;
            _usb_control_complete(adapter);
        }

        else if (URB_Status == URB_ERROR) {
            ctl_req->state = CTRL_ERROR;  
        }
        else if (URB_Status == URB_STALL) {
            ctl_req->state = URB_STALL;  /* NOTICE: here maybe a error to be fixed!!! */
        }
        
        break;

    case CTRL_STATUS_OUT:
        USB_OTG_BSP_uDelay(200);
        pdev->host.hc[ctl_req->hc_num_out].toggle_out ^= 1; 
        USBH_CtlSendData(pdev,
                        0,
                        0,
                        ctl_req->hc_num_out);

        ctl_req->state = CTRL_STATUS_OUT_WAIT;
        break;

    case CTRL_STATUS_OUT_WAIT: 
        URB_Status = HCD_GetURB_State(pdev, ctl_req->hc_num_out);
        ctl_req->status = URB_Status;
        
        if (URB_Status == URB_DONE) { 
            ctl_req->state = CTRL_IDLE;
            _usb_control_complete(adapter);
        }
        else if (URB_Status == URB_NOTREADY) { 
            ctl_req->state = CTRL_STATUS_OUT;
        }      
        else if (URB_Status == URB_ERROR) {
            ctl_req->state = CTRL_ERROR; 
        }
        break;

    case CTRL_ERROR:
        DBGPRINT(WHED_DEBUG_ERROR, "PANIC(%s - %d): %s - control urb failed(%d), bRequestType = 0x%x, bRequest = 0x%x, wValue = 0x%x, wIndex = 0x%x, wLength = 0x%x.\n", 
                __FILE__, __LINE__, __FUNCTION__, 
                ctl_req->status,
                ctl_req->ctrlreq.b.bmRequestType,
                ctl_req->ctrlreq.b.bRequest,
                ctl_req->ctrlreq.b.wValue.w,
                ctl_req->ctrlreq.b.wIndex.w,
                ctl_req->ctrlreq.b.wLength.w);
        if (ctl_req->retry) {
            ctl_req->retry--;
            /* Do the transmission again, starting from SETUP Packet. */
            ctl_req->state = CTRL_SETUP; 
        }
        else {
            ctl_req->state = CTRL_IDLE;
            _usb_control_complete(adapter);
        }
        break;

    default:
        break;
    }
    
    timeout = timeout; /* avoid compiler's warning */

    return status;
}
Beispiel #6
0
static int _usb_bulkin_request_handle(USB_OTG_CORE_HANDLE * pdev , 
                                      USBH_HOST * phost, 
                                      wifi_usb_adapter_t *adapter)
{
    wifi_usb_bulkin_request_t *rx_req = &adapter->usb_rx_req;
    static unsigned short timeout = 0;
    URB_STATE URB_Status = URB_IDLE;
    unsigned int actual_len = 0;
    int status = 1;

    switch (rx_req->state) {
    case USB_BULK_STATE_IDLE:
        status = 0; /* indicate the state machine could be blocked */
        break;

    case USB_BULK_STATE_REQUEST:
        rx_req->packet_buffer = &rx_req->buffer[0];
        rx_req->packet_len = pdev->host.hc[adapter->hc_num_in].max_packet;
        
        USBH_BulkReceiveData(pdev, rx_req->packet_buffer, rx_req->packet_len, adapter->hc_num_in);

        rx_req->retry = 3;
        rx_req->state = USB_BULK_STATE_REQUEST_WAIT;
        status = 0; /* indicate the state machine could be blocked */
        timeout = BULK_DATA_STAGE_TIMEOUT;
        /* Set the delay timer to enable timeout for data stage completion. */
        rx_req->timer = HCD_GetCurrentFrame(pdev);
        break;

    case USB_BULK_STATE_REQUEST_WAIT:
        URB_Status = HCD_GetURB_State(pdev , adapter->hc_num_in);
        rx_req->status = URB_Status;
  
        if (URB_Status == URB_DONE) { 
            rx_req->state = USB_BULK_STATE_IDLE;
            actual_len = pdev->host.hc[adapter->hc_num_in].xfer_count;
            rx_req->len += actual_len;
            rx_req->packet_buffer = (unsigned char *)(rx_req->packet_buffer) + actual_len;

            if (actual_len < pdev->host.hc[adapter->hc_num_in].max_packet) {
                _usb_bulkin_complete(adapter);
            }
            else {
                if ((rx_req->len + pdev->host.hc[adapter->hc_num_in].max_packet) <= NOSWIFI_USB_RX_BUFFER_MAX_LEN) {
                    rx_req->packet_len = pdev->host.hc[adapter->hc_num_in].max_packet;
                    USBH_BulkReceiveData(pdev, rx_req->packet_buffer, rx_req->packet_len, adapter->hc_num_in);

                    rx_req->retry = 3;
                    rx_req->state = USB_BULK_STATE_REQUEST_WAIT;
                    status = 0; /* indicate the state machine could be blocked */
                    timeout = BULK_DATA_STAGE_TIMEOUT;
                    /* Set the delay timer to enable timeout for data stage completion. */
                    rx_req->timer = HCD_GetCurrentFrame(pdev);
                }
                else {
                    rx_req->len = 0;
                    _usb_bulkin_complete(adapter);
                }
            }
        }
        else if (URB_Status == URB_ERROR) {
            rx_req->state = USB_BULK_STATE_ERROR;
        }    
        else if (URB_Status == URB_STALL) {
            rx_req->state = USB_BULK_STATE_ERROR;
        }
        break;

    case USB_BULK_STATE_ERROR:
        DBGPRINT(WHED_DEBUG_ERROR, "PANIC(%s - %d): %s - rx urb failed(%d).\n", __FILE__, __LINE__, __FUNCTION__, rx_req->status);
        if (rx_req->retry) {
            USB_OTG_BSP_uDelay(600);
            rx_req->retry--;
            rx_req->state = USB_BULK_STATE_REQUEST; 
        }
        else {
            rx_req->state = USB_BULK_STATE_REQUEST;
            rx_req->state = USB_BULK_STATE_IDLE;
            rx_req->len = 0;
            _usb_bulkin_complete(adapter);
        }
        break;

    default:
        break;
    }

    timeout = timeout; /* avoid compiler's warning */

    return status;
}
Beispiel #7
0
static int _usb_bulkout_request_handle(USB_OTG_CORE_HANDLE *pdev , 
                                       USBH_HOST *phost, 
                                       wifi_usb_adapter_t *adapter)
{
    wifi_usb_bulkout_request_t *tx_req = &adapter->usb_tx_req;
    static unsigned short timeout = 0;
    URB_STATE URB_Status = URB_IDLE;
    int status = 1;

    switch (tx_req->state) {
    case USB_BULK_STATE_IDLE:
        status = 0; /* indicate the state machine could be blocked */
        break;

    case USB_BULK_STATE_REQUEST:
        tx_req->packet_buffer = &tx_req->buffer[0];
        if (tx_req->len > pdev->host.hc[adapter->hc_num_out].max_packet) {
            tx_req->packet_len = pdev->host.hc[adapter->hc_num_out].max_packet;
        }
        else {
            tx_req->packet_len = tx_req->len;
        }
        
        USBH_BulkSendData(pdev, tx_req->packet_buffer, tx_req->packet_len, adapter->hc_num_out);

        tx_req->retry = 3;
        tx_req->state = USB_BULK_STATE_REQUEST_WAIT;
        status = 0; /* indicate the state machine could be blocked */
        timeout = BULK_DATA_STAGE_TIMEOUT;
        /* Set the delay timer to enable timeout for data stage completion. */
        tx_req->timer = HCD_GetCurrentFrame(pdev);
        break;

    case USB_BULK_STATE_REQUEST_WAIT:
        URB_Status = HCD_GetURB_State(pdev , adapter->hc_num_out);
        tx_req->status = URB_Status;
  
        if (URB_Status == URB_DONE) {
            tx_req->len -= tx_req->packet_len;
            tx_req->packet_buffer = (unsigned char *)(tx_req->packet_buffer) + tx_req->packet_len;

            if (tx_req->len == 0) {
                tx_req->state = USB_BULK_STATE_IDLE;
                _usb_bulkout_complete(adapter);
            }
            else {
                if (tx_req->len > pdev->host.hc[adapter->hc_num_out].max_packet) {
                    tx_req->packet_len = pdev->host.hc[adapter->hc_num_out].max_packet;
                }
                else {
                    tx_req->packet_len = tx_req->len;
                }

                USBH_BulkSendData(pdev, tx_req->packet_buffer, tx_req->packet_len, adapter->hc_num_out);

                tx_req->retry = 10;
                tx_req->state = USB_BULK_STATE_REQUEST_WAIT;
                status = 0; /* indicate the state machine could be blocked */
                timeout = BULK_DATA_STAGE_TIMEOUT;
                /* Set the delay timer to enable timeout for data stage completion. */
                tx_req->timer = HCD_GetCurrentFrame(pdev);
            }
        }
        else if (URB_Status == URB_ERROR) {
            tx_req->state = USB_BULK_STATE_ERROR;
        }    
        else if (URB_Status == URB_STALL) {
            tx_req->state = USB_BULK_STATE_ERROR;
        }
        else if (URB_Status == URB_NOTREADY) {
            USBH_BulkSendData(pdev, tx_req->packet_buffer, tx_req->packet_len, adapter->hc_num_out);
            tx_req->state = USB_BULK_STATE_REQUEST_WAIT;
            status = 0; /* indicate the state machine could be blocked */
            timeout = BULK_DATA_STAGE_TIMEOUT;
            /* Set the delay timer to enable timeout for data stage completion. */
            tx_req->timer = HCD_GetCurrentFrame(pdev);
        } 
        break;

    case USB_BULK_STATE_ERROR:
        DBGPRINT(WHED_DEBUG_ERROR, "PANIC(%s - %d): %s - tx urb failed(%d).\n", __FILE__, __LINE__, __FUNCTION__, tx_req->status);
        if (tx_req->retry) {
            tx_req->retry--;
            //USB_OTG_BSP_uDelay(600);
            USBH_BulkSendData(pdev, tx_req->packet_buffer, tx_req->packet_len, adapter->hc_num_out);
            tx_req->state = USB_BULK_STATE_REQUEST_WAIT;
            status = 0; /* indicate the state machine could be blocked */
            timeout = BULK_DATA_STAGE_TIMEOUT;
            /* Set the delay timer to enable timeout for data stage completion. */
            tx_req->timer = HCD_GetCurrentFrame(pdev);
        }
        else {
            tx_req->state = USB_BULK_STATE_REQUEST;
            tx_req->state = USB_BULK_STATE_IDLE;
            _usb_bulkout_complete(adapter);
        }
        break;

    default:
        break;
    }

    timeout = timeout; /* avoid compiler's warning */

    return status;
}