/**
******************************************************************************
* @file usbh_ioreq.c
* @author MCD Application Team
* @version V2.1.0
* @date 19-March-2012
* @brief This file handles the issuing of the USB transactions
******************************************************************************
* @attention
*
*
© COPYRIGHT 2012 STMicroelectronics
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbh_ioreq.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_LIB_CORE
* @{
*/
/** @defgroup USBH_IOREQ
* @brief This file handles the standard protocol processing (USB v2.0)
* @{
*/
/** @defgroup USBH_IOREQ_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBH_IOREQ_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBH_IOREQ_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_IOREQ_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_IOREQ_Private_FunctionPrototypes
* @{
*/
static USBH_Status USBH_SubmitSetupRequest(USBH_HOST *phost,
uint8_t* buff,
uint16_t length);
/**
* @}
*/
/** @defgroup USBH_IOREQ_Private_Functions
* @{
*/
/**
* @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,
USBH_HOST *phost,
uint8_t *buff,
uint16_t length)
{
USBH_Status status;
status = USBH_BUSY;
switch (phost->RequestState)
{
case CMD_SEND:
/* Start a SETUP transfer */
USBH_SubmitSetupRequest(phost, buff, length);
phost->RequestState = CMD_WAIT;
status = USBH_BUSY;
break;
case CMD_WAIT:
if (phost->Control.state == CTRL_COMPLETE )
{
/* Commands successfully sent and Response Received */
phost->RequestState = CMD_SEND;
phost->Control.state =CTRL_IDLE;
status = USBH_OK;
}
else if (phost->Control.state == CTRL_ERROR)
{
/* Failure Mode */
phost->RequestState = CMD_SEND;
status = USBH_FAIL;
}
else if (phost->Control.state == CTRL_STALLED )
{
/* Commands successfully sent and Response Received */
phost->RequestState = CMD_SEND;
status = USBH_NOT_SUPPORTED;
}
break;
default:
break;
}
return status;
}
/**
* @brief USBH_CtlSendSetup
* Sends the Setup Packet to the Device
* @param pdev: Selected device
* @param buff: Buffer pointer from which the Data will be send to Device
* @param hc_num: Host channel Number
* @retval Status
*/
USBH_Status USBH_CtlSendSetup ( USB_OTG_CORE_HANDLE *pdev,
uint8_t *buff,
uint8_t hc_num){
pdev->host.hc[hc_num].ep_is_in = 0;
pdev->host.hc[hc_num].data_pid = HC_PID_SETUP;
pdev->host.hc[hc_num].xfer_buff = buff;
pdev->host.hc[hc_num].xfer_len = USBH_SETUP_PKT_SIZE;
return (USBH_Status)HCD_SubmitRequest (pdev , hc_num);
}
/**
* @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,
uint16_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 ( 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;
}
/**
* @brief USBH_CtlReceiveData
* Receives the Device Response to the Setup Packet
* @param pdev: Selected device
* @param buff: Buffer pointer in which the response needs to be copied
* @param length: Length of the data to be received
* @param hc_num: Host channel Number
* @retval Status.
*/
USBH_Status USBH_CtlReceiveData(USB_OTG_CORE_HANDLE *pdev,
uint8_t* buff,
uint16_t length,
uint8_t hc_num)
{
pdev->host.hc[hc_num].ep_is_in = 1;
pdev->host.hc[hc_num].data_pid = HC_PID_DATA1;
pdev->host.hc[hc_num].xfer_buff = buff;
pdev->host.hc[hc_num].xfer_len = length;
HCD_SubmitRequest (pdev , hc_num);
return USBH_OK;
}
/**
* @brief USBH_BulkSendData
* Sends the Bulk 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_BulkSendData ( USB_OTG_CORE_HANDLE *pdev,
uint8_t *buff,
uint16_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;
/* 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;
}
/**
* @brief USBH_BulkReceiveData
* Receives IN bulk packet from device
* @param pdev: Selected device
* @param buff: Buffer pointer in which the received data packet to be copied
* @param length: Length of the data to be received
* @param hc_num: Host channel Number
* @retval Status.
*/
USBH_Status USBH_BulkReceiveData( USB_OTG_CORE_HANDLE *pdev,
uint8_t *buff,
uint16_t length,
uint8_t hc_num)
{
pdev->host.hc[hc_num].ep_is_in = 1;
pdev->host.hc[hc_num].xfer_buff = buff;
pdev->host.hc[hc_num].xfer_len = length;
if( pdev->host.hc[hc_num].toggle_in == 0)
{
pdev->host.hc[hc_num].data_pid = HC_PID_DATA0;
}
else
{
pdev->host.hc[hc_num].data_pid = HC_PID_DATA1;
}
HCD_SubmitRequest (pdev , hc_num);
return USBH_OK;
}
/**
* @brief USBH_InterruptReceiveData
* Receives the Device Response to the Interrupt IN token
* @param pdev: Selected device
* @param buff: Buffer pointer in which the response needs to be copied
* @param length: Length of the data to be received
* @param hc_num: Host channel Number
* @retval Status.
*/
USBH_Status USBH_InterruptReceiveData( USB_OTG_CORE_HANDLE *pdev,
uint8_t *buff,
uint8_t length,
uint8_t hc_num)
{
pdev->host.hc[hc_num].ep_is_in = 1;
pdev->host.hc[hc_num].xfer_buff = buff;
pdev->host.hc[hc_num].xfer_len = length;
if(pdev->host.hc[hc_num].toggle_in == 0)
{
pdev->host.hc[hc_num].data_pid = HC_PID_DATA0;
}
else
{
pdev->host.hc[hc_num].data_pid = HC_PID_DATA1;
}
/* toggle DATA PID */
pdev->host.hc[hc_num].toggle_in ^= 1;
HCD_SubmitRequest (pdev , hc_num);
return USBH_OK;
}
/**
* @brief USBH_InterruptSendData
* Sends the data on Interrupt OUT Endpoint
* @param pdev: Selected device
* @param buff: Buffer pointer from where the data needs to be copied
* @param length: Length of the data to be sent
* @param hc_num: Host channel Number
* @retval Status.
*/
USBH_Status USBH_InterruptSendData( 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(pdev->host.hc[hc_num].toggle_in == 0)
{
pdev->host.hc[hc_num].data_pid = HC_PID_DATA0;
}
else
{
pdev->host.hc[hc_num].data_pid = HC_PID_DATA1;
}
pdev->host.hc[hc_num].toggle_in ^= 1;
HCD_SubmitRequest (pdev , hc_num);
return USBH_OK;
}
/**
* @brief USBH_SubmitSetupRequest
* Start a setup transfer by changing the state-machine and
* initializing the required variables needed for the Control Transfer
* @param pdev: Selected device
* @param setup: Setup Request Structure
* @param buff: Buffer used for setup request
* @param length: Length of the data
* @retval Status.
*/
static USBH_Status USBH_SubmitSetupRequest(USBH_HOST *phost,
uint8_t* buff,
uint16_t length)
{
/* Save Global State */
phost->gStateBkp = phost->gState;
/* Prepare the Transactions */
phost->gState = HOST_CTRL_XFER;
phost->Control.buff = buff;
phost->Control.length = length;
phost->Control.state = CTRL_SETUP;
return USBH_OK;
}
/**
* @brief USBH_IsocReceiveData
* Receives the Device Response to the Isochronous IN token
* @param pdev: Selected device
* @param buff: Buffer pointer in which the response needs to be copied
* @param length: Length of the data to be received
* @param hc_num: Host channel Number
* @retval Status.
*/
USBH_Status USBH_IsocReceiveData( USB_OTG_CORE_HANDLE *pdev,
uint8_t *buff,
uint32_t length,
uint8_t hc_num)
{
pdev->host.hc[hc_num].ep_is_in = 1;
pdev->host.hc[hc_num].xfer_buff = buff;
pdev->host.hc[hc_num].xfer_len = length;
pdev->host.hc[hc_num].data_pid = HC_PID_DATA0;
HCD_SubmitRequest (pdev , hc_num);
return USBH_OK;
}
/**
* @brief USBH_IsocSendData
* Sends the data on Isochronous OUT Endpoint
* @param pdev: Selected device
* @param buff: Buffer pointer from where the data needs to be copied
* @param length: Length of the data to be sent
* @param hc_num: Host channel Number
* @retval Status.
*/
USBH_Status USBH_IsocSendData( USB_OTG_CORE_HANDLE *pdev,
uint8_t *buff,
uint32_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;
pdev->host.hc[hc_num].data_pid = HC_PID_DATA0;
HCD_SubmitRequest (pdev , hc_num);
return USBH_OK;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/