Beispiel #1
0
static void CDC_ProcessReception(USBH_HandleTypeDef *phost)
{
  CDC_HandleTypeDef *CDC_Handle =  (CDC_HandleTypeDef*) phost->pActiveClass->pData;
  USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE;
  uint16_t length;

  switch(CDC_Handle->data_rx_state)
  {
    
  case CDC_RECEIVE_DATA:

    USBH_BulkReceiveData (phost,
                          CDC_Handle->pRxData, 
                          CDC_Handle->DataItf.InEpSize, 
                          CDC_Handle->DataItf.InPipe);
    
    CDC_Handle->data_rx_state = CDC_RECEIVE_DATA_WAIT;
    
    break;
    
  case CDC_RECEIVE_DATA_WAIT:
    
    URB_Status = USBH_LL_GetURBState(phost, CDC_Handle->DataItf.InPipe); 
    
    /*Check the status done for reception*/
    if(URB_Status == USBH_URB_DONE )
    {  
      length = USBH_LL_GetLastXferSize(phost, CDC_Handle->DataItf.InPipe);
        
      if(((CDC_Handle->RxDataLength - length) > 0) && (length > CDC_Handle->DataItf.InEpSize))
      {
        CDC_Handle->RxDataLength -= length ;
        CDC_Handle->pRxData += length;
        CDC_Handle->data_rx_state = CDC_RECEIVE_DATA; 
      }
      else
      {
        CDC_Handle->data_rx_state = CDC_IDLE;
        USBH_CDC_ReceiveCallback(phost);
      }
#if (USBH_USE_OS == 1)
      osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0);
#endif          
    }
    break;
    
  default:
    break;
  }
}
/**
  * @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;
    }
  }
}
static USBH_StatusTypeDef USBH_AOA_InHandle(USBH_HandleTypeDef *phost)
{
  USBH_URBStateTypeDef URB_Status;
  uint32_t size;
  AOA_HandleTypeDef* aoa = phost->pActiveClass->pData;

  switch (aoa->inState)
  {
  case AOA_RECV_DATA:
    USBH_BulkReceiveData(phost, aoa->inbuff, USBH_AOA_DATA_SIZE,
        aoa->hc_num_in);

    aoa->inState = AOA_RECV_DATA_WAIT;
    break;

  case AOA_RECV_DATA_WAIT:
    URB_Status = USBH_LL_GetURBState(phost, aoa->hc_num_in);
    if (URB_Status == USBH_URB_DONE)
    {
      size = USBH_LL_GetLastXferSize(phost, aoa->hc_num_in);

      if (size > 0) {

        if (DebugConfig.print_aoa_recvdata)
        {
          if (printable(aoa->inbuff, size)) {
            aoa->inbuff[size] = '\0';
            USBH_UsrLog("AOA: in %u bytes, \"%s\"", (unsigned int)size, aoa->inbuff);
          }
          else {
            USBH_UsrLog("AOA: in %u bytes, %s", (unsigned int)size, bytes2bin(aoa->inbuff, size));
          }
        }

        if (aoa->recvCallback)
        {
          aoa->recvCallback(phost, aoa->inbuff, size);
        }

        aoa->inState = AOA_RECV_DATA;
      }
    }
    break;
  }

  return USBH_OK;
}
/**
  * @brief  USBH_MSC_BOT_Process 
  *         The function handle the BOT protocol.
  * @param  phost: Host handle
  * @param  lun: Logical Unit Number
  * @retval USBH Status
  */
USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun)
{
  USBH_StatusTypeDef   status = USBH_BUSY;
  USBH_StatusTypeDef   error  = USBH_BUSY;  
  BOT_CSWStatusTypeDef CSW_Status = BOT_CSW_CMD_FAILED;
  USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE;
  MSC_HandleTypeDef *MSC_Handle =  (MSC_HandleTypeDef *) phost->pActiveClass->pData;
  uint8_t toggle = 0;
  
  switch (MSC_Handle->hbot.state)
  {
  case BOT_SEND_CBW:
    MSC_Handle->hbot.cbw.field.LUN = lun;
    MSC_Handle->hbot.state = BOT_SEND_CBW_WAIT;    
    USBH_BulkSendData (phost,
                       MSC_Handle->hbot.cbw.data, 
                       BOT_CBW_LENGTH, 
                       MSC_Handle->OutPipe,
                       1);
    
    break;
    
  case BOT_SEND_CBW_WAIT:
    
    URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->OutPipe); 
    
    if(URB_Status == USBH_URB_DONE)
    { 
      if ( MSC_Handle->hbot.cbw.field.DataTransferLength != 0 )
      {
        /* If there is Data Transfer Stage */
        if (((MSC_Handle->hbot.cbw.field.Flags) & USB_REQ_DIR_MASK) == USB_D2H)
        {
          /* Data Direction is IN */
          MSC_Handle->hbot.state = BOT_DATA_IN;
        }
        else
        {
          /* Data Direction is OUT */
          MSC_Handle->hbot.state = BOT_DATA_OUT;
        } 
      }
      
      else
      {/* If there is NO Data Transfer Stage */
        MSC_Handle->hbot.state = BOT_RECEIVE_CSW;
      }
#if (USBH_USE_OS == 1)
    osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif   
    
    }   
    else if(URB_Status == USBH_URB_NOTREADY)
    {
      /* Re-send CBW */
      MSC_Handle->hbot.state = BOT_SEND_CBW;
#if (USBH_USE_OS == 1)
    osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif       
    }     
    else if(URB_Status == USBH_URB_STALL)
    {
      MSC_Handle->hbot.state  = BOT_ERROR_OUT;
#if (USBH_USE_OS == 1)
    osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif       
    }
    break;
    
  case BOT_DATA_IN:   
    /* Send first packet */        
    USBH_BulkReceiveData (phost,
                          MSC_Handle->hbot.pbuf, 
                          MSC_Handle->InEpSize , 
                          MSC_Handle->InPipe);
    
    MSC_Handle->hbot.state  = BOT_DATA_IN_WAIT;
    
    break;   
    
  case BOT_DATA_IN_WAIT:  
    
    URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->InPipe); 
    
    if(URB_Status == USBH_URB_DONE) 
    {
      /* Adjust Data pointer and data length */
      if(MSC_Handle->hbot.cbw.field.DataTransferLength > MSC_Handle->InEpSize)
      {
          MSC_Handle->hbot.pbuf += MSC_Handle->InEpSize;
          MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->InEpSize;  
      }
      else
      {
        MSC_Handle->hbot.cbw.field.DataTransferLength = 0;
      }
        
      /* More Data To be Received */
      if(MSC_Handle->hbot.cbw.field.DataTransferLength > 0)
      {
        /* Send next packet */        
        USBH_BulkReceiveData (phost,
                              MSC_Handle->hbot.pbuf, 
                              MSC_Handle->InEpSize , 
                              MSC_Handle->InPipe);
        
      }
      else
      {
        /* If value was 0, and successful transfer, then change the state */
        MSC_Handle->hbot.state  = BOT_RECEIVE_CSW;
#if (USBH_USE_OS == 1)
        osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif 
      }
    }
    else if(URB_Status == USBH_URB_STALL)
    {
      /* This is Data IN Stage STALL Condition */
      MSC_Handle->hbot.state  = 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.*/
      
#if (USBH_USE_OS == 1)
    osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif       
    }     
    break;  
    
  case BOT_DATA_OUT:
    
    USBH_BulkSendData (phost,
                       MSC_Handle->hbot.pbuf, 
                       MSC_Handle->OutEpSize , 
                       MSC_Handle->OutPipe,
                       1);
    
    
    MSC_Handle->hbot.state  = BOT_DATA_OUT_WAIT;
    break;
    
  case BOT_DATA_OUT_WAIT:
    URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->OutPipe);     
    
    if(URB_Status == USBH_URB_DONE)
    {
      /* Adjust Data pointer and data length */
      if(MSC_Handle->hbot.cbw.field.DataTransferLength > MSC_Handle->OutEpSize)
      {
          MSC_Handle->hbot.pbuf += MSC_Handle->OutEpSize;
          MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->OutEpSize; 
      }
      else
      {
        MSC_Handle->hbot.cbw.field.DataTransferLength = 0;
      } 
      
      /* More Data To be Sent */
      if(MSC_Handle->hbot.cbw.field.DataTransferLength > 0)
      {
        USBH_BulkSendData (phost,
                           MSC_Handle->hbot.pbuf, 
                           MSC_Handle->OutEpSize , 
                           MSC_Handle->OutPipe,
                           1);
      }
      else
      {
        /* If value was 0, and successful transfer, then change the state */
        MSC_Handle->hbot.state  = BOT_RECEIVE_CSW;
      }  
#if (USBH_USE_OS == 1)
    osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif       
    }
    
    else if(URB_Status == USBH_URB_NOTREADY)
    {
      /* Resend same data */      
      MSC_Handle->hbot.state  = BOT_DATA_OUT;
#if (USBH_USE_OS == 1)
    osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif       
    }
    
    else if(URB_Status == USBH_URB_STALL)
    {
      MSC_Handle->hbot.state  = 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.
      */      
#if (USBH_USE_OS == 1)
      osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif       
    }
    break;
    
  case BOT_RECEIVE_CSW:
    
    USBH_BulkReceiveData (phost,
                          MSC_Handle->hbot.csw.data, 
                          BOT_CSW_LENGTH , 
                          MSC_Handle->InPipe);
    
    MSC_Handle->hbot.state  = BOT_RECEIVE_CSW_WAIT;
    break;
    
  case BOT_RECEIVE_CSW_WAIT:
    
    URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->InPipe); 
    
    /* Decode CSW */
    if(URB_Status == USBH_URB_DONE)
    {
      MSC_Handle->hbot.state = BOT_SEND_CBW;    
      MSC_Handle->hbot.cmd_state = BOT_CMD_SEND;        
      CSW_Status = USBH_MSC_DecodeCSW(phost);
      
      if(CSW_Status == BOT_CSW_CMD_PASSED)
      {
        status = USBH_OK;
      }
      else
      {
        status = USBH_FAIL;
      }
#if (USBH_USE_OS == 1)
      osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif       
    }
    else if(URB_Status == USBH_URB_STALL)     
    {
      MSC_Handle->hbot.state  = BOT_ERROR_IN;
#if (USBH_USE_OS == 1)
      osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
#endif       
    }
    break;
    
  case BOT_ERROR_IN: 
    error = USBH_MSC_BOT_Abort(phost, lun, BOT_DIR_IN);
    
    if (error == USBH_OK)
    {
      MSC_Handle->hbot.state = BOT_RECEIVE_CSW;
    }
    else if (error == USBH_UNRECOVERED_ERROR)
    {
      /* This means that there is a STALL Error limit, Do Reset Recovery */
      MSC_Handle->hbot.state = BOT_UNRECOVERED_ERROR;
    }
    break;
    
  case BOT_ERROR_OUT: 
    error = USBH_MSC_BOT_Abort(phost, lun, BOT_DIR_OUT);
    
    if ( error == USBH_OK)
    { 
      
      toggle = USBH_LL_GetToggle(phost, MSC_Handle->OutPipe); 
      USBH_LL_SetToggle(phost, MSC_Handle->OutPipe, 1- toggle);   
      USBH_LL_SetToggle(phost, MSC_Handle->InPipe, 0);  
      MSC_Handle->hbot.state = BOT_ERROR_IN;        
    }
    else if (error == USBH_UNRECOVERED_ERROR)
    {
      MSC_Handle->hbot.state = BOT_UNRECOVERED_ERROR;
    }
    break;
    
    
  case BOT_UNRECOVERED_ERROR: 
    status = USBH_MSC_BOT_REQ_Reset(phost);
    if ( status == USBH_OK)
    {
      MSC_Handle->hbot.state = BOT_SEND_CBW; 
    }
    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
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 #8
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;
}