/**
  * @brief  This function responsible for reception of data from the device
  * @param  pdev: Selected device
  * @retval None
  */
static void CDC_ProcessReception(USB_OTG_CORE_HANDLE *pdev, USBH_HOST *phost)
{
  
  if(RX_Enabled == 1)
  {
    URB_STATE URB_StatusRx =   HCD_GetURB_State(pdev , CDC_Machine.CDC_DataItf.hc_num_in);  
    
    switch(CDC_RxParam.CDCState)
    {
      
    case CDC_IDLE:
      
      
      /*check the received length lesser then the remaining space available in the 
      buffer */
      if(CDC_RxParam.DataLength < (CDC_RxParam.BufferLen - CDC_Machine.CDC_DataItf.length))
      {
        /*Receive the data */
        USBH_BulkReceiveData(pdev,
                             CDC_RxParam.pFillBuff,
                             CDC_Machine.CDC_DataItf.length, 
                             CDC_Machine.CDC_DataItf.hc_num_in);
        
        /*change the cdc state to USBH_CDC_GET_DATA*/
        CDC_RxParam.CDCState = CDC_GET_DATA;
      }
      break;
      
    case CDC_GET_DATA:
      /*Check the last state of the device is URB_DONE */
      if(URB_StatusRx == URB_DONE)
      {
        /* Move the pointer as well as datalength */
        CDC_RxParam.DataLength += pdev->host.hc[CDC_Machine.CDC_DataItf.hc_num_in].xfer_count ;
        CDC_RxParam.pFillBuff += pdev->host.hc[CDC_Machine.CDC_DataItf.hc_num_in].xfer_count ;
        
        
        /* Process the recived data */
        CDC_ReceiveData(&CDC_RxParam);
        
        /*change the state od the CDC state*/
        CDC_RxParam.CDCState = CDC_IDLE;
        
      }
      break;
    }
  }
}
Beispiel #2
0
/**
  * @brief  USBH_CtlReq
  *         USBH_CtlReq sends a control request and provide the status after 
  *            completion of the request
  * @param  pdev: Selected device
  * @param  req: Setup Request Structure
  * @param  buff: data buffer address to store the response
  * @param  length: length of the response
  * @retval Status
  */
USBH_Status USBH_CtlReq     (USB_OTG_CORE_HANDLE *pdev, 
                             USB_Setup_TypeDef   *req,
                             uint8_t             *buff,
                             uint16_t            length)
{
  USBH_Status status;
  URB_STATE URB_Status = URB_IDLE;
  
  URB_Status = HCD_GetURB_State(pdev); 
  
  status = USBH_BUSY;
  
  switch (USBH_Machine.RequestState)
  {
  case CMD_SEND:
    /* Start a SETUP transfer */
    USBH_SubmitSetupRequest(pdev, req, buff, length);
    USBH_Machine.RequestState = CMD_WAIT;
    status = USBH_BUSY;
    break;
    
  case CMD_WAIT:
    if  (URB_Status == URB_DONE)
    {
      /* Commands successfully sent and Response Received  */       
      USBH_Machine.RequestState = CMD_SEND;
      status = USBH_OK;
    }
    else if  (URB_Status == URB_ERROR)
    {
      /* Failure Mode */
      USBH_Machine.RequestState = CMD_SEND;
      status = USBH_FAIL;
    }   
     else if  (URB_Status == URB_STALL)
    {
      /* Commands successfully sent and Response Received  */       
      USBH_Machine.RequestState = CMD_SEND;
      status = USBH_NOT_SUPPORTED;
    }
    break;
    
  default:
    break; 
  }
  return status;
}
Beispiel #3
0
/**
  * @brief  USBH_CtlSendData
  *         Sends a data Packet to the Device
  * @param  pdev: Selected device
  * @param  buff: Buffer pointer from which the Data will be sent to Device
  * @param  length: Length of the data to be sent
  * @param  hc_num: Host channel Number
  * @retval Status
  */
USBH_Status USBH_CtlSendData ( USB_OTG_CORE_HANDLE *pdev, 
                                uint8_t *buff, 
                                uint8_t length,
                                uint8_t hc_num)
{
  pdev->host.hc[hc_num].ep_is_in = 0;
  pdev->host.hc[hc_num].xfer_buff = buff;
  pdev->host.hc[hc_num].xfer_len = length;
  
  
  
  if(HCD_GetURB_State(pdev) == URB_DONE)
  { 
    /* Toggle the Bit fore previous successful Transaction */ 
     pdev->host.hc[hc_num].toggle_out ^= 1; 
  }
 
  if ( length == 0 )
  { /* For Status OUT stage, Length==0, Status Out PID = 1 */
    pdev->host.hc[hc_num].toggle_out = 1;   
  }
 
 /* Set the Data Toggle bit as per the Flag */
  if ( pdev->host.hc[hc_num].toggle_out == 0)
  { /* Put the PID 0 */
      pdev->host.hc[hc_num].data_pid = HC_PID_DATA0;    
  }
 else
 { /* Put the PID 1 */
      pdev->host.hc[hc_num].data_pid = HC_PID_DATA1 ;
 }

  HCD_SubmitRequest (pdev , hc_num);   
   
  return USBH_OK;
}
Beispiel #4
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;
}
/**
 * @brief  USBH_MSC_HandleBOTXfer 
 *         This function manages the different states of BOT transfer and 
 *         updates the status to upper layer.
 * @param  None
 * @retval None
 * 
 */
void USBH_MSC_HandleBOTXfer(USB_OTG_CORE_HANDLE *pdev, USBH_HOST *phost) {
    uint8_t xferDirection, index;
    static uint32_t remainingDataLength;
    static uint8_t *datapointer, *datapointer_prev;
    static uint8_t error_direction;
    USBH_Status status;

    URB_STATE URB_Status = URB_IDLE;

    if (HCD_IsDeviceConnected(pdev)) {

        switch (USBH_MSC_BOTXferParam.BOTState) {
        case USBH_MSC_SEND_CBW:
            /* send CBW */
            USBH_BulkSendData(pdev, &USBH_MSC_CBWData.CBWArray[0],
            USBH_MSC_BOT_CBW_PACKET_LENGTH, MSC_Machine.hc_num_out);

            USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_SEND_CBW;
            USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SENT_CBW;

            break;

        case USBH_MSC_SENT_CBW:
            URB_Status = HCD_GetURB_State(pdev, MSC_Machine.hc_num_out);

            if (URB_Status == URB_DONE) {
                BOTStallErrorCount = 0;
                USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_SENT_CBW;

                /* If the CBW Pkt is sent successful, then change the state */
                xferDirection = (USBH_MSC_CBWData.field.CBWFlags
                        & USB_REQ_DIR_MASK);

                if (USBH_MSC_CBWData.field.CBWTransferLength != 0) {
                    remainingDataLength =
                            USBH_MSC_CBWData.field.CBWTransferLength;
                    datapointer = USBH_MSC_BOTXferParam.pRxTxBuff;
                    datapointer_prev = datapointer;

                    /* If there is Data Transfer Stage */
                    if (xferDirection == USB_D2H) {
                        /* Data Direction is IN */
                        USBH_MSC_BOTXferParam.BOTState =
                                USBH_MSC_BOT_DATAIN_STATE;
                    } else {
                        /* Data Direction is OUT */
                        USBH_MSC_BOTXferParam.BOTState =
                                USBH_MSC_BOT_DATAOUT_STATE;
                    }
                }

                else {/* If there is NO Data Transfer Stage */
                    USBH_MSC_BOTXferParam.BOTState = USBH_MSC_RECEIVE_CSW_STATE;
                }

            } else if (URB_Status == URB_NOTREADY) {
                USBH_MSC_BOTXferParam.BOTState =
                        USBH_MSC_BOTXferParam.BOTStateBkp;
            } else if (URB_Status == URB_STALL) {
                error_direction = USBH_MSC_DIR_OUT;
                USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_OUT;
            }
            break;

        case USBH_MSC_BOT_DATAIN_STATE:

            URB_Status = HCD_GetURB_State(pdev, MSC_Machine.hc_num_in);
            /* BOT DATA IN stage */
            if ((URB_Status == URB_DONE)
                    || (USBH_MSC_BOTXferParam.BOTStateBkp
                            != USBH_MSC_BOT_DATAIN_STATE)) {
                BOTStallErrorCount = 0;
                USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_BOT_DATAIN_STATE;

                if (remainingDataLength > MSC_Machine.MSBulkInEpSize) {
                    USBH_BulkReceiveData(pdev, datapointer,
                            MSC_Machine.MSBulkInEpSize, MSC_Machine.hc_num_in);

                    remainingDataLength -= MSC_Machine.MSBulkInEpSize;
                    datapointer = datapointer + MSC_Machine.MSBulkInEpSize;
                } else if (remainingDataLength == 0) {
                    /* If value was 0, and successful transfer, then change the state */
                    USBH_MSC_BOTXferParam.BOTState = USBH_MSC_RECEIVE_CSW_STATE;
                } else {
                    USBH_BulkReceiveData(pdev, datapointer, remainingDataLength,
                            MSC_Machine.hc_num_in);

                    remainingDataLength = 0; /* Reset this value and keep in same state */
                }
            } else if (URB_Status == URB_STALL) {
                /* This is Data Stage STALL Condition */

                error_direction = USBH_MSC_DIR_IN;
                USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_IN;

                /* Refer to USB Mass-Storage Class : BOT (www.usb.org) 
                 6.7.2 Host expects to receive data from the device
                 3. On a STALL condition receiving data, then:
                 The host shall accept the data received.
                 The host shall clear the Bulk-In pipe.
                 4. The host shall attempt to receive a CSW.
                 
                 USBH_MSC_BOTXferParam.BOTStateBkp is used to switch to the Original 
                 state after the ClearFeature Command is issued.
                 */
                USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE;

            }
            break;

        case USBH_MSC_BOT_DATAOUT_STATE:
            /* BOT DATA OUT stage */
            URB_Status = HCD_GetURB_State(pdev, MSC_Machine.hc_num_out);
            if (URB_Status == URB_DONE) {
                BOTStallErrorCount = 0;
                USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_BOT_DATAOUT_STATE;
                if (remainingDataLength > MSC_Machine.MSBulkOutEpSize) {
                    USBH_BulkSendData(pdev, datapointer,
                            MSC_Machine.MSBulkOutEpSize,
                            MSC_Machine.hc_num_out);
                    datapointer_prev = datapointer;
                    datapointer = datapointer + MSC_Machine.MSBulkOutEpSize;

                    remainingDataLength = remainingDataLength
                            - MSC_Machine.MSBulkOutEpSize;
                } else if (remainingDataLength == 0) {
                    /* If value was 0, and successful transfer, then change the state */
                    USBH_MSC_BOTXferParam.BOTState = USBH_MSC_RECEIVE_CSW_STATE;
                } else {
                    USBH_BulkSendData(pdev, datapointer, remainingDataLength,
                            MSC_Machine.hc_num_out);

                    remainingDataLength = 0; /* Reset this value and keep in same state */
                }
            }

            else if (URB_Status == URB_NOTREADY) {
                if (datapointer != datapointer_prev) {
                    USBH_BulkSendData(pdev,
                            (datapointer - MSC_Machine.MSBulkOutEpSize),
                            MSC_Machine.MSBulkOutEpSize,
                            MSC_Machine.hc_num_out);
                } else {
                    USBH_BulkSendData(pdev, datapointer,
                            MSC_Machine.MSBulkOutEpSize,
                            MSC_Machine.hc_num_out);
                }
            }

            else if (URB_Status == URB_STALL) {
                error_direction = USBH_MSC_DIR_OUT;
                USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_OUT;

                /* Refer to USB Mass-Storage Class : BOT (www.usb.org) 
                 6.7.3 Ho - Host expects to send data to the device
                 3. On a STALL condition sending data, then:
                 " The host shall clear the Bulk-Out pipe.
                 4. The host shall attempt to receive a CSW.
                 
                 The Above statement will do the clear the Bulk-Out pipe.
                 The Below statement will help in Getting the CSW.  
                 
                 USBH_MSC_BOTXferParam.BOTStateBkp is used to switch to the Original 
                 state after the ClearFeature Command is issued.
                 */

                USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE;

            }
            break;

        case USBH_MSC_RECEIVE_CSW_STATE:
            /* BOT CSW stage */
            /* NOTE: We cannot reset the BOTStallErrorCount here as it may come from 
             the clearFeature from previous command */

            USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE;

            USBH_MSC_BOTXferParam.pRxTxBuff = USBH_MSC_CSWData.CSWArray;
            USBH_MSC_BOTXferParam.DataLength = USBH_MSC_CSW_MAX_LENGTH;

            for (index = USBH_MSC_CSW_LENGTH; index != 0; index--) {
                USBH_MSC_CSWData.CSWArray[index] = 0;
            }

            USBH_MSC_CSWData.CSWArray[0] = 0;

            USBH_BulkReceiveData(pdev, USBH_MSC_BOTXferParam.pRxTxBuff,
            USBH_MSC_CSW_MAX_LENGTH, MSC_Machine.hc_num_in);
            USBH_MSC_BOTXferParam.BOTState = USBH_MSC_DECODE_CSW;

            break;

        case USBH_MSC_DECODE_CSW:
            URB_Status = HCD_GetURB_State(pdev, MSC_Machine.hc_num_in);
            /* Decode CSW */
            if (URB_Status == URB_DONE) {
                BOTStallErrorCount = 0;
                USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE;

                USBH_MSC_BOTXferParam.MSCState =
                        USBH_MSC_BOTXferParam.MSCStateCurrent;

                USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_DecodeCSW(pdev,
                        phost);
            } else if (URB_Status == URB_STALL) {
                error_direction = USBH_MSC_DIR_IN;
                USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_IN;
            }
            break;

        case USBH_MSC_BOT_ERROR_IN:
            status = USBH_MSC_BOT_Abort(pdev, phost, USBH_MSC_DIR_IN);
            if (status == USBH_OK) {
                /* Check if the error was due in Both the directions */
                if (error_direction == USBH_MSC_BOTH_DIR) {/* If Both directions are Needed, Switch to OUT Direction */
                    USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_OUT;
                } else {
                    /* Switch Back to the Original State, In many cases this will be 
                     USBH_MSC_RECEIVE_CSW_STATE state */
                    USBH_MSC_BOTXferParam.BOTState =
                            USBH_MSC_BOTXferParam.BOTStateBkp;
                }
            } else if (status == USBH_UNRECOVERED_ERROR) {
                /* This means that there is a STALL Error limit, Do Reset Recovery */
                USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_PHASE_ERROR;
            }
            break;

        case USBH_MSC_BOT_ERROR_OUT:
            status = USBH_MSC_BOT_Abort(pdev, phost, USBH_MSC_DIR_OUT);
            if (status == USBH_OK) { /* Switch Back to the Original State */
                USBH_MSC_BOTXferParam.BOTState =
                        USBH_MSC_BOTXferParam.BOTStateBkp;
            } else if (status == USBH_UNRECOVERED_ERROR) {
                /* This means that there is a STALL Error limit, Do Reset Recovery */
                USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_PHASE_ERROR;
            }
            break;

        default:
            break;
        }
    }
}
/**
 * This function will do bulk transfer in lowlevel, it will send request to the host controller
 *
 * @param pipe the bulk transfer pipe. 
 * @param buffer the data buffer to save requested data
 * @param nbytes the size of buffer
 * 
 * @return the error code, RT_EOK on successfully.
 */
static int susb_bulk_xfer(upipe_t pipe, void* buffer, int nbytes, int timeout)
{    
    rt_uint8_t channel;
    int left = nbytes;
    rt_uint8_t *ptr;
    URB_STATE state;

    RT_ASSERT(pipe != RT_NULL);
    RT_ASSERT(buffer != RT_NULL);

    if(!(root_hub.port_status[0] & PORT_CCS) || 
        (root_hub.port_status[0] & PORT_CCSC)) return -1;

    ptr = (rt_uint8_t*)buffer;
    channel = (rt_uint32_t)pipe->user_data & 0xFF;
    
    rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
    
    if(pipe->ep.bEndpointAddress & USB_DIR_IN)
    {    
        while(left > pipe->ep.wMaxPacketSize)
        {
            USBH_BulkReceiveData(&USB_OTG_Core, ptr, pipe->ep.wMaxPacketSize, 
                channel);
            while(1)
            {
                state = HCD_GetURB_State(&USB_OTG_Core , channel);
                if(state == URB_DONE) break;
                else if(state == URB_NOTREADY) rt_kprintf("not ready\n");
                else if(state == URB_STALL) rt_kprintf("stall\n");
                //else if(state == URB_IDLE) rt_kprintf("idle\n");
            }
            
            ptr += pipe->ep.wMaxPacketSize;
            left -= pipe->ep.wMaxPacketSize;
        }

        USBH_BulkReceiveData(&USB_OTG_Core, ptr, left, channel);
        while(1)
        {
            state = HCD_GetURB_State(&USB_OTG_Core , channel);
            if(state == URB_DONE) break;
            else if(state == URB_NOTREADY) rt_kprintf("not ready\n");
            else if(state == URB_STALL) rt_kprintf("stall\n");
            //else if(state == URB_IDLE) rt_kprintf("idle\n");            
        }
    }    
    else
    {    
send_data:
        while(left > pipe->ep.wMaxPacketSize)
        {
            USBH_BulkSendData(&USB_OTG_Core, ptr, pipe->ep.wMaxPacketSize, 
                channel);

            while(1)
            {
                state = HCD_GetURB_State(&USB_OTG_Core, channel);
                if(state == URB_DONE) break;
                if(state == URB_NOTREADY) goto send_data;
            }

            ptr += pipe->ep.wMaxPacketSize;
            left -= pipe->ep.wMaxPacketSize;        
        }        

        USBH_BulkSendData(&USB_OTG_Core, ptr, left, channel);    
        while(1)
        {
            state = HCD_GetURB_State(&USB_OTG_Core , channel);
            if(state == URB_DONE) break;
            if(state == URB_NOTREADY) goto send_data;
        }        
    }

    rt_sem_release(&sem_lock);
    return nbytes;
}
Beispiel #7
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 #8
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 #9
0
void USBPT_Work()
{
	if (USBPT_Has_Dev == 0)
	{
		if (HCD_IsDeviceConnected(&USB_OTG_Core_host) != 0)
		{
			USBPT_printf("USBPT Device Connecting \r\n");

			if (USBH_Open_Channel(	&USB_OTG_Core_host,
					&(USBPT_Dev->Control.hc_num_in),
					0x80,
					USBPT_Dev->device_prop.address, // still 0 at this point
					USBPT_Dev->device_prop.speed,
					EP_TYPE_CTRL,
					USBPT_Dev->Control.ep0size) == HC_OK
				&&
				USBH_Open_Channel(	&USB_OTG_Core_host,
					&(USBPT_Dev->Control.hc_num_out),
					0x00,
					USBPT_Dev->device_prop.address, // still 0 at this point
					USBPT_Dev->device_prop.speed,
					EP_TYPE_CTRL,
					USBPT_Dev->Control.ep0size) == HC_OK
			) {
				DCD_DevConnect(&USB_OTG_Core_dev);
				USBPT_Has_Dev = 1;
			}
			else
			{
				dbg_printf(DBGMODE_ERR, "USBPT Unable to allocate control EP HC \r\n");
			}
		}
		else
		{
			return;
		}
	}
	else
	{
		if (HCD_IsDeviceConnected(&USB_OTG_Core_host) == 0)
		{
			USBPT_printf("USBPT Device Disconnecting \r\n");
			USBD_DeInit(&USB_OTG_Core_dev);
			DCD_DevDisconnect(&USB_OTG_Core_dev);
			USBPT_Has_Dev = 0;

			for (uint8_t i = 0; i < USBPTH_MAX_LISTENERS; i++)
			{
				USBH_Free_Channel(&USB_OTG_Core_host, &(USBPTH_Listeners[i].hc));
			}

			USBH_Free_Channel(&USB_OTG_Core_host, &(USBPT_Dev->Control.hc_num_out));
			USBH_Free_Channel(&USB_OTG_Core_host, &(USBPT_Dev->Control.hc_num_in));
		}
	}

	for (uint8_t i = 0; i < USBPTH_MAX_LISTENERS; i++)
	{
		USBPTH_HC_EP_t* pl = &USBPTH_Listeners[i];
		int8_t hc = USBPTH_Listeners[i].hc;
		if (hc >= 0) // if listener is actually allocated
		{
			USBH_EpDesc_TypeDef* epDesc = pl->epDesc;
			uint8_t epnum = epDesc->bEndpointAddress;
			uint8_t epType = 0;
			USBPT_GeneralInDataLen = epDesc->wMaxPacketSize;

			// try to send read tokens only on even frames
			if (USB_OTG_IsEvenFrame(&USB_OTG_Core_host) == 0) continue;

			dbg_trace();

			// attempt to start the read, check the read type first
			if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_INTR) {
				epType = EP_TYPE_INTR;
				USBH_InterruptReceiveData(&USB_OTG_Core_host, USBPT_GeneralInData, USBPT_GeneralInDataLen, hc);
			}
			else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_BULK) {
				epType = EP_TYPE_BULK;
				USBH_BulkReceiveData(&USB_OTG_Core_host, USBPT_GeneralInData, USBPT_GeneralInDataLen, hc);
			}
			else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_ISOC) {
				epType = EP_TYPE_ISOC;
				USBH_IsocReceiveData(&USB_OTG_Core_host, USBPT_GeneralInData, USBPT_GeneralInDataLen, hc);
			}

			// now we wait for a reply, or maybe there isn't one
			USBH_Status status;
			char sent = 0;
			delay_1ms_cnt = 100;
			do
			{
				URB_STATE us = HCD_GetURB_State(&USB_OTG_Core_host, hc);
				if (us == URB_DONE)
				{
					// data was indeed received

					// print it to the serial port for monitoring
					USBPT_printf("USBPT:IN:EP0x%02X:", epnum);
					for (uint16_t c = 0; c < USBPT_GeneralInDataLen; c++) {
						USBPT_printf(" 0x%02X", USBPT_GeneralInData[c]);
					}
					USBPT_printf("\r\n");

					// relay the data to the host
					DCD_EP_Tx(&USB_OTG_Core_dev, epnum, USBPT_GeneralInData, USBPT_GeneralInDataLen);
					sent = 1;
					break;
				}
				else if (us == URB_ERROR) {
					dbg_printf(DBGMODE_ERR, "DataIn Error on EP 0x%02X \r\n", epnum);
					break;
				}
				else if (us == URB_STALL) {
					dbg_printf(DBGMODE_ERR, "DataIn Stalled EP 0x%02X \r\n", epnum);
					break;
				}
				else if (us == URB_NOTREADY) {
					// NAK, no data
					break;
				}
			}
			while (delay_1ms_cnt > 0);

			if (delay_1ms_cnt == 0) {
				dbg_printf(DBGMODE_ERR, "DataIn Read Timed Out EP 0x%02X \r\n", epnum);
			}
		}
	}
}
Beispiel #10
0
uint8_t USBPTD_DataOut           (void *pcore , uint8_t epnum)
{
	USB_OTG_CORE_HANDLE* pcore_ = (USB_OTG_CORE_HANDLE*)pcore;
	DCD_DEV* pdev = &(pcore_->dev);
	uint8_t* data;
	uint16_t wLength;

	if (epnum == 0x00)
	{ // CTRL REQ
		wLength = USBPT_CtrlDataLen;
		data = USBPT_CtrlData;
	}
	else
	{
		wLength = pdev->out_ep[epnum].xfer_count;
		data = pdev->out_ep[epnum].xfer_buff;
	}

	// print to monitor
	USBPT_printf("USBPT:OUT:EP0x%02X:", epnum);
	for (uint16_t i = 0; i < wLength; i++) {
		USBPT_printf(" 0x%02X", data[i]);
	}
	USBPT_printf("\r\n");

	if (epnum == 0x00)
	{ // CTRL REQ

		USBH_Status status;
		delay_1ms_cnt = 100;

		// wait for transfer complete
		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) {
			dbg_printf(DBGMODE_ERR, "USBPTD_DataOut timed out while sending to device, status: 0x%04X \r\n", status);
			USBD_CtlError(pcore , 0);
			return USBD_FAIL;
		}
		else if (status != USBH_OK) {
			dbg_printf(DBGMODE_ERR, "USBPTD_DataOut failed to send to device, status: 0x%04X \r\n", status);
			USBD_CtlError(pcore , 0);
			return USBD_FAIL;
		}
		else { // everything is OK
			USBD_CtlSendStatus(pcore);
			return USBD_OK;
		}
	}
	else
	{
		wLength = pdev->out_ep[epnum].xfer_count;
		data = pdev->out_ep[epnum].xfer_buff;

		// allocate memory needed
		if (USBPT_GeneralOutData != 0) free(USBPT_GeneralOutData);
		USBPT_GeneralOutDataLen = wLength;
		USBPT_GeneralOutData = malloc(wLength);
		memcpy(USBPT_GeneralOutData, data, USBPT_GeneralOutDataLen);

		USBH_EpDesc_TypeDef* epDesc = 0;
		for (uint8_t i = 0; i < USBPTH_OutEPCnt; i++)
		{
			// look for appropriate EP
			if (USBPTH_OutEP[i]->bEndpointAddress == epnum) {
				epDesc = USBPTH_OutEP[i];
				break;
			}
		}

		if (epDesc != 0) // EP found
		{
			uint8_t epType = 0;
			int8_t hc = -1;
			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;
			}

			// dynamically allocate host channel for use
			if (USBH_Open_Channel(	&USB_OTG_Core_host,
									&hc,
									epnum,
									USBPT_Dev->device_prop.address,
									USBPT_Dev->device_prop.speed,
									epType,
									epDesc->wMaxPacketSize) == HC_OK)
			{

				// try to only send on even frame
				volatile uint32_t syncTries = 0x7FFFFFFF;
				while (USB_OTG_IsEvenFrame(&USB_OTG_Core_host) == 0 && syncTries--) __NOP();

				// send using appropriate method
				switch (epType)
				{
					case EP_TYPE_INTR:
						USBH_InterruptSendData(&USB_OTG_Core_host, USBPT_GeneralOutData, USBPT_GeneralOutDataLen, hc);
						break;
					case EP_TYPE_BULK:
						USBH_BulkSendData(&USB_OTG_Core_host, USBPT_GeneralOutData, USBPT_GeneralOutDataLen, hc);
						break;
					case EP_TYPE_ISOC:
						USBH_IsocSendData(&USB_OTG_Core_host, USBPT_GeneralOutData, USBPT_GeneralOutDataLen, hc);
						break;
					default:
						break;
				}

				// wait until done sending
				USBH_Status status;
				delay_1ms_cnt = 100;
				do
				{
					URB_STATE us = HCD_GetURB_State(&USB_OTG_Core_host, hc);
					if (us == URB_DONE) {
						break;
					}
					else if (us == URB_ERROR) {
						dbg_printf(DBGMODE_ERR, "USBPTD_DataOut Send Error on EP 0x%02X \r\n", epnum);
						DCD_EP_Stall(pcore, epnum);
						break;
					}
					else if (us == URB_STALL) {
						dbg_printf(DBGMODE_ERR, "USBPTD_DataOut Stalled EP 0x%02X \r\n", epnum);
						DCD_EP_Stall(pcore, epnum);
						break;
					}
				}
				while (delay_1ms_cnt > 0);

				if (delay_1ms_cnt == 0) {
					dbg_printf(DBGMODE_ERR, "USBPTD_DataOut Send Timed Out EP 0x%02X \r\n", epnum);
				}

				// free the channel to be used by something else later
				USBH_Free_Channel(&USB_OTG_Core_host, &hc);
			}
			else
			{
				dbg_printf(DBGMODE_ERR, "USBPTD_DataOut Failed to Alloc HC for EP 0x%02X \r\n", epnum);
			}

		}
		else
		{
			dbg_printf(DBGMODE_ERR, "USBPTD_DataOut No Such EP 0x%02X \r\n", epnum);
		}

		return USBD_OK;
	}

	return USBD_OK;
}
Beispiel #11
0
/* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout                       */
uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit, uint8_t *data_p = NULL, uint16_t nbytes = 0, uint8_t hcnum = 0) {
        unsigned long timeout = millis() + USB_XFER_TIMEOUT;
        //unsigned long timeout2 = timeout;
        uint8_t tmpdata;
        uint8_t rcode = hrSUCCESS;
        uint8_t retry_count = 0;
        uint16_t nak_count = 0;
        USB_OTG_CORE_HANDLE *pdev = coreConfig;
        uint8_t pid = 0;

		pdev->host.hc[hcnum].nak_count = 0;
		pdev->host.hc[hcnum].nak_limit = nak_limit;

        while (timeout > millis()) {
			//regWr(rHXFR, (token | ep)); //launch the transfer
        	if(token == tokSETUP) {
				USBH_CtlSendSetup(pdev, data_p, hcnum);
				//timeout2 = millis() + 10;
        	} else {
        		if(token == tokOUTHS) {
        			pdev->host.hc[hcnum].toggle_out = 0x1;
        			pdev->host.hc[hcnum].ep_is_in = 0;
        			pid = HC_PID_DATA1;
        		} else if (token == tokINHS) {
        			pdev->host.hc[hcnum].toggle_in = 0x1;
        			pdev->host.hc[hcnum].ep_is_in = 1;
        			pid = HC_PID_DATA1;
        		} else if (token == tokIN){
        			pdev->host.hc[hcnum].ep_is_in = 1;
        			pid = (pdev->host.hc[hcnum].toggle_in)? HC_PID_DATA1 : HC_PID_DATA0;
        		} else {
        			pdev->host.hc[hcnum].ep_is_in = 0;
        			pid = (pdev->host.hc[hcnum].toggle_out)? HC_PID_DATA1 : HC_PID_DATA0;
        		}/*
        		if(pid == HC_PID_DATA0) {
        			STM_EVAL_LEDToggle(LED1);
        			delay_ms(1);
        			STM_EVAL_LEDToggle(LED1);
        			delay_ms(1);
        			STM_EVAL_LEDToggle(LED1);
        		}
        		if(pid == HC_PID_DATA1) {
        			STM_EVAL_LEDToggle(LED1);
        			delay_ms(1);
					STM_EVAL_LEDToggle(LED1);
					delay_ms(1);
					STM_EVAL_LEDToggle(LED1);
					delay_ms(1);
					STM_EVAL_LEDToggle(LED1);
        		}*/
    			pdev->host.hc[hcnum].data_pid = pid;
    			pdev->host.hc[hcnum].xfer_buff = data_p;
    			pdev->host.hc[hcnum].xfer_len = nbytes;

    			HCD_SubmitRequest(pdev, hcnum);
        	}

			rcode = USB_ERROR_TRANSFER_TIMEOUT;
			while (timeout > millis()) //wait for transfer completion
			{
				tmpdata = HCD_GetURB_State(pdev, hcnum);	//regRd(rHIRQ);
				if (tmpdata != URB_IDLE) {	//& bmHXFRDNIRQ) {
					//regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt
					rcode = 0x00;
					break;
				} 
				if (pdev->host.ConnSts == 0) {
					rcode = hrJERR;
					return rcode;
				}
/*				else {	//todo: because in bt case, there are two in ep (int-in, bulk-in), that we need to check hid/msc case either.
					rcode = HCD_GetHCState(pdev, hcnum);
					if(rcode == hrNAK) {
						nak_count++;
						if (nak_limit && (nak_count == nak_limit))
							return (rcode);
						uint8_t eptype = pdev->host.hc[hcnum].ep_type;
						if (eptype == EP_TYPE_INTR) {
							break;
						} else if ((eptype == EP_TYPE_CTRL) || (eptype == EP_TYPE_BULK)) {					      // re-activate the channel
							USB_OTG_HCCHAR_TypeDef hcchar;
							hcchar.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[hcnum]->HCCHAR);
							hcchar.b.chen = 1;
							hcchar.b.chdis = 0;
							USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hcnum]->HCCHAR, hcchar.d32);
							delay_us(200);
						}
					}
				}*/
			}

			//if (rcode != 0x00) //exit if timeout
			//        return ( rcode);

            rcode = HCD_GetHCState(pdev, hcnum);	//(regRd(rHRSL) & 0x0f); //analyze transfer result
			switch (rcode) {
				case hrNAK: 	//todo: if timeout above with nak, we need to consider the next xfer.
					nak_count = pdev->host.hc[hcnum].nak_count;
					if (nak_limit && (nak_count == nak_limit))
						return (rcode);
					break;
				case hrTIMEOUT:
					retry_count++;
					if (retry_count == USB_RETRY_LIMIT)
						return (rcode);
					break;
				default:
					return (rcode);
			}

        }//while( timeout > millis()

        return ( rcode);
}
Beispiel #12
0
uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data) {
	uint8_t rcode = hrSUCCESS, retry_count;
	uint8_t *data_p = data; //local copy of the data pointer
	uint16_t bytes_tosend, nak_count;
	uint16_t bytes_left = nbytes, last_bytesleft = nbytes;
	USB_OTG_CORE_HANDLE *pdev = coreConfig;
	uint32_t hcnum = pep->hcNumOut;

	uint8_t maxpktsize = pep->maxPktSize;

	if (maxpktsize < 1 || maxpktsize > 64)
		return USB_ERROR_INVALID_MAX_PKT_SIZE;

	if(maxpktsize != pdev->host.hc[hcnum].max_packet)
			pdev->host.hc[hcnum].max_packet = maxpktsize;
#if 0
	pdev->host.hc[hcnum].ep_is_in = 0;
	pdev->host.hc[hcnum].xfer_buff = data; //buff;
	pdev->host.hc[hcnum].xfer_len = nbytes;	//length;

	if(nbytes == 0)
	{ /* For Status OUT stage, Length==0, Status Out PID = 1 */
		pdev->host.hc[hcnum].toggle_out = 1;
	}

	/* Set the Data Toggle bit as per the Flag */
	if ( pdev->host.hc[hcnum].toggle_out == 0)
	{ /* Put the PID 0 */
		pdev->host.hc[hcnum].data_pid = HC_PID_DATA0;
	}
	else
	{ /* Put the PID 1 */
		pdev->host.hc[hcnum].data_pid = HC_PID_DATA1 ;
	}

	HCD_SubmitRequest (pdev, hcnum);
#else
        unsigned long timeout = millis() + USB_XFER_TIMEOUT;

        //regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
    	pdev->host.hc[hcnum].ep_is_in = 0;
    	pdev->host.hc[hcnum].xfer_buff = data; //buff;
    	pdev->host.hc[hcnum].xfer_len = nbytes;	//length;

    	if(nbytes == 0)
    	{ /* For Status OUT stage, Length==0, Status Out PID = 1 */
    		pdev->host.hc[hcnum].toggle_out = 1;
    	}

    	/* Set the Data Toggle bit as per the Flag */
    	if ( pdev->host.hc[hcnum].toggle_out == 0)
    	{ /* Put the PID 0 */
    		pdev->host.hc[hcnum].data_pid = HC_PID_DATA0;
    	}
    	else
    	{ /* Put the PID 1 */
    		pdev->host.hc[hcnum].data_pid = HC_PID_DATA1 ;
    	}

		retry_count = 0;
		nak_count = 0;
		while (bytes_left) {
			// we send all data at once due to large fifo
			//bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left;
			//bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO
			//regWr(rSNDBC, bytes_tosend); //set number of bytes
			//regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
			HCD_SubmitRequest(pdev, hcnum);
PollStatus:
			rcode = USB_ERROR_TRANSFER_TIMEOUT;
			while (timeout > millis())  //while (!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ
			{
				rcode = HCD_GetURB_State(pdev, hcnum);	//regRd(rHIRQ);
				if (rcode != URB_IDLE) {	//& bmHXFRDNIRQ) {
					//regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
					rcode = 0x00;
					break;
				}
			}
			if(rcode != 0x00)
				return rcode;	// todo: return for what

			rcode = HCD_GetHCState(pdev, hcnum);	//(regRd(rHRSL) & 0x0f);
			//while (rcode && (timeout > millis())) {	// we don't need pulling here because we already did it above
				switch (rcode) {
					case hrNAK:
						nak_count++;	//maybe a NOT_READY happens
						if (nak_limit && (nak_count == nak_limit))
							goto breakout;
/*						else if (URB_NOTREADY == HCD_GetURB_State(pdev, hcnum)) {
							USB_OTG_HCCHAR_TypeDef hcchar;
							hcchar.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[hcnum]->HCCHAR);
							if(hcchar.b.eptype == EP_TYPE_BULK) {
								pdev->host.URB_State[hcnum] = URB_IDLE;
								// re-activate the channel
								hcchar.b.chen = 1;
								hcchar.b.chdis = 0;
								USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hcnum]->HCCHAR, hcchar.d32);
			                    STM_EVAL_LEDToggle(LED1);
								goto PollStatus;	//return ( rcode);
							}
						}*/
						break;
					case hrTIMEOUT:
						retry_count++;
						if (retry_count == USB_RETRY_LIMIT)
							goto breakout;
						//return ( rcode);
						break;
					case hrTOGERR:
						// yes, we flip it wrong here so that next time it is actually correct!
						//pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
						//regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
						printf("\nOutTransfer - togerr");
						//break;
					default:
						goto breakout;
				}//switch( rcode

				/* process NAK according to Host out NAK bug */
/*				uint32_t *addr;
				uint32_t i;
				for(addr = (uint32_t *)0x50000000, i = 0; i < 0x12; addr++, i++) {
					printf("\naddr(%x) = %x", addr, *addr);
				}*/
				USB_OTG_HCTSIZn_TypeDef hctsiz;
				hctsiz.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[hcnum]->HCTSIZ);

				bytes_left = hctsiz.b.pktcnt << 6;
				if(last_bytesleft != bytes_left) {
					last_bytesleft = bytes_left;
					pdev->host.hc[hcnum].xfer_buff = data + nbytes - bytes_left;
					pdev->host.hc[hcnum].xfer_len = bytes_left;

					if(((nbytes - bytes_left) >> 6) & 0x1) {	// if sent odd times packets
						pdev->host.hc[hcnum].toggle_out ^= 0x1;
						pdev->host.hc[hcnum].data_pid = (pdev->host.hc[hcnum].toggle_out) ? HC_PID_DATA1 : HC_PID_DATA0;
					}
					pdev->host.hc[hcnum].isEvenTimesToggle = 0;	// will be re-calculate in HCD_SubmitRequest
					retry_count = 0;
					nak_count = 0;
				}
				//regWr(rSNDBC, 0);
				//regWr(rSNDFIFO, *data_p);
				//regWr(rSNDBC, bytes_tosend);
				//regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
				//while (!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ
				//regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
				//rcode = (regRd(rHRSL) & 0x0f);
			//}//while( rcode && ....
			// bytes_left seems never decreasing to 0
			//bytes_left -= bytes_tosend;
			//data_p += bytes_tosend;
		}//while( bytes_left...
/**
  * @brief  The function is responsible for sending data to the device
  * @param  pdev: Selected device
  * @retval None
  */
void CDC_ProcessTransmission(USB_OTG_CORE_HANDLE *pdev, USBH_HOST *phost)
{
  static uint32_t len ;
  URB_STATE URB_StatusTx = URB_IDLE;
  
  URB_StatusTx =   HCD_GetURB_State(pdev , CDC_Machine.CDC_DataItf.hc_num_out);
  
  switch(CDC_TxParam.CDCState)
  {
  case CDC_IDLE:
    break;
    
  case CDC_SEND_DATA:
    
    if(( URB_StatusTx == URB_DONE ) || (URB_StatusTx == URB_IDLE))
    {
      /*Check the data length is more then the CDC_Machine.CDC_DataItf.CDC_DataItf.length */
      if(CDC_TxParam.DataLength > CDC_Machine.CDC_DataItf.length)
      {
        
        len = CDC_Machine.CDC_DataItf.length ;
        /*Send the data */
        USBH_BulkSendData (pdev,
                           CDC_TxParam.pRxTxBuff, 
                           len , 
                           CDC_Machine.CDC_DataItf.hc_num_out);    
      }
      else
      {
        len = CDC_TxParam.DataLength ;
        /*Send the remaining data */
        USBH_BulkSendData (pdev,
                           CDC_TxParam.pRxTxBuff, 
                           len, 
                           CDC_Machine.CDC_DataItf.hc_num_out);
        
      }
      CDC_TxParam.CDCState = CDC_DATA_SENT;
      
    }
    
    break;
    
  case CDC_DATA_SENT:
    /*Check the status done for transmssion*/
    if(URB_StatusTx == URB_DONE )
    {         
      /*Point to next chunc of data*/
      CDC_TxParam.pRxTxBuff += len ;
      
      /*decrease the data length*/
      CDC_TxParam.DataLength -= len;    
      
      if(CDC_TxParam.DataLength == 0)
      {
        CDC_TxParam.CDCState = CDC_IDLE;
      }
      else
      {
        CDC_TxParam.CDCState = CDC_SEND_DATA; 
      }
    }
    else if( URB_StatusTx == URB_NOTREADY )
    {
      /*Send the same data */
      USBH_BulkSendData (pdev,
                         (CDC_TxParam.pRxTxBuff), 
                         len, 
                         CDC_Machine.CDC_DataItf.hc_num_out);
    }
    
    break;
    
  }
}
Beispiel #14
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 #15
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 #16
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;
}