|
|
|
@ -4,25 +4,17 @@
|
|
|
|
|
******************************************************************************
|
|
|
|
|
* @file usbd_core.c
|
|
|
|
|
* @author MCD Application Team
|
|
|
|
|
* @version V2.4.2
|
|
|
|
|
* @date 11-December-2015
|
|
|
|
|
* @brief This file provides all the USBD core functions.
|
|
|
|
|
******************************************************************************
|
|
|
|
|
* @attention
|
|
|
|
|
*
|
|
|
|
|
* <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2>
|
|
|
|
|
* <h2><center>© Copyright (c) 2015 STMicroelectronics.
|
|
|
|
|
* All rights reserved.</center></h2>
|
|
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
* This software component is licensed by ST under Ultimate Liberty license
|
|
|
|
|
* SLA0044, 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/SLA0044
|
|
|
|
|
*
|
|
|
|
|
******************************************************************************
|
|
|
|
|
*/
|
|
|
|
@ -100,7 +92,9 @@ USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef *
|
|
|
|
|
/* Check whether the USB Host handle is valid */
|
|
|
|
|
if(pdev == NULL)
|
|
|
|
|
{
|
|
|
|
|
#if (USBD_DEBUG_LEVEL > 1U)
|
|
|
|
|
USBD_ErrLog("Invalid Device handle");
|
|
|
|
|
#endif
|
|
|
|
|
return USBD_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -137,7 +131,7 @@ USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev)
|
|
|
|
|
pdev->dev_state = USBD_STATE_DEFAULT;
|
|
|
|
|
|
|
|
|
|
/* Free Class Resources */
|
|
|
|
|
pdev->pClass->DeInit(pdev, pdev->dev_config);
|
|
|
|
|
pdev->pClass->DeInit(pdev, (uint8_t)pdev->dev_config);
|
|
|
|
|
|
|
|
|
|
/* Stop the low level driver */
|
|
|
|
|
USBD_LL_Stop(pdev);
|
|
|
|
@ -148,7 +142,6 @@ USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev)
|
|
|
|
|
return USBD_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief USBD_RegisterClass
|
|
|
|
|
* Link class driver to Device Core.
|
|
|
|
@ -167,7 +160,9 @@ USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeD
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
#if (USBD_DEBUG_LEVEL > 1U)
|
|
|
|
|
USBD_ErrLog("Invalid Class handle");
|
|
|
|
|
#endif
|
|
|
|
|
status = USBD_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -198,7 +193,7 @@ USBD_StatusTypeDef USBD_Start (USBD_HandleTypeDef *pdev)
|
|
|
|
|
USBD_StatusTypeDef USBD_Stop (USBD_HandleTypeDef *pdev)
|
|
|
|
|
{
|
|
|
|
|
/* Free Class Resources */
|
|
|
|
|
pdev->pClass->DeInit(pdev, pdev->dev_config);
|
|
|
|
|
pdev->pClass->DeInit(pdev, (uint8_t)pdev->dev_config);
|
|
|
|
|
|
|
|
|
|
/* Stop the low level driver */
|
|
|
|
|
USBD_LL_Stop(pdev);
|
|
|
|
@ -214,10 +209,12 @@ USBD_StatusTypeDef USBD_Stop (USBD_HandleTypeDef *pdev)
|
|
|
|
|
*/
|
|
|
|
|
USBD_StatusTypeDef USBD_RunTestMode (USBD_HandleTypeDef *pdev)
|
|
|
|
|
{
|
|
|
|
|
/* Prevent unused argument compilation warning */
|
|
|
|
|
UNUSED(pdev);
|
|
|
|
|
|
|
|
|
|
return USBD_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief USBD_SetClassConfig
|
|
|
|
|
* Configure device and start the interface
|
|
|
|
@ -233,11 +230,12 @@ USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx
|
|
|
|
|
if(pdev->pClass != NULL)
|
|
|
|
|
{
|
|
|
|
|
/* Set configuration and Start the Class*/
|
|
|
|
|
if(pdev->pClass->Init(pdev, cfgidx) == 0)
|
|
|
|
|
if(pdev->pClass->Init(pdev, cfgidx) == 0U)
|
|
|
|
|
{
|
|
|
|
|
ret = USBD_OK;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -264,10 +262,10 @@ USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx
|
|
|
|
|
*/
|
|
|
|
|
USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
USBD_ParseSetupRequest(&pdev->request, psetup);
|
|
|
|
|
|
|
|
|
|
pdev->ep0_state = USBD_EP0_SETUP;
|
|
|
|
|
|
|
|
|
|
pdev->ep0_data_len = pdev->request.wLength;
|
|
|
|
|
|
|
|
|
|
switch (pdev->request.bmRequest & USB_REQ_TYPE_MASK)
|
|
|
|
@ -286,7 +284,7 @@ USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup)
|
|
|
|
|
USBD_StdEPReq(pdev, &pdev->request);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
USBD_LL_StallEP(pdev, pdev->request.bmRequest & 0x80);
|
|
|
|
|
USBD_LL_StallEP(pdev, (pdev->request.bmRequest & 0x80U));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
@ -311,11 +309,12 @@ USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup)
|
|
|
|
|
* @param epnum: endpoint index
|
|
|
|
|
* @retval status
|
|
|
|
|
*/
|
|
|
|
|
USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata)
|
|
|
|
|
USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev,
|
|
|
|
|
uint8_t epnum, uint8_t *pdata)
|
|
|
|
|
{
|
|
|
|
|
USBD_EndpointTypeDef *pep;
|
|
|
|
|
|
|
|
|
|
if(epnum == 0)
|
|
|
|
|
if(epnum == 0U)
|
|
|
|
|
{
|
|
|
|
|
pep = &pdev->ep_out[0];
|
|
|
|
|
|
|
|
|
@ -327,7 +326,7 @@ USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum
|
|
|
|
|
|
|
|
|
|
USBD_CtlContinueRx (pdev,
|
|
|
|
|
pdata,
|
|
|
|
|
MIN(pep->rem_length ,pep->maxpacket));
|
|
|
|
|
(uint16_t)MIN(pep->rem_length, pep->maxpacket));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
@ -339,12 +338,29 @@ USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum
|
|
|
|
|
USBD_CtlSendStatus(pdev);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (pdev->ep0_state == USBD_EP0_STATUS_OUT)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* STATUS PHASE completed, update ep0_state to idle
|
|
|
|
|
*/
|
|
|
|
|
pdev->ep0_state = USBD_EP0_IDLE;
|
|
|
|
|
USBD_LL_StallEP(pdev, 0U);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if((pdev->pClass->DataOut != NULL) &&
|
|
|
|
|
(pdev->dev_state == USBD_STATE_CONFIGURED))
|
|
|
|
|
{
|
|
|
|
|
pdev->pClass->DataOut(pdev, epnum);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* should never be in this condition */
|
|
|
|
|
return USBD_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return USBD_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -355,11 +371,12 @@ USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum
|
|
|
|
|
* @param epnum: endpoint index
|
|
|
|
|
* @retval status
|
|
|
|
|
*/
|
|
|
|
|
USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev ,uint8_t epnum, uint8_t *pdata)
|
|
|
|
|
USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev, uint8_t epnum,
|
|
|
|
|
uint8_t *pdata)
|
|
|
|
|
{
|
|
|
|
|
USBD_EndpointTypeDef *pep;
|
|
|
|
|
|
|
|
|
|
if(epnum == 0)
|
|
|
|
|
if(epnum == 0U)
|
|
|
|
|
{
|
|
|
|
|
pep = &pdev->ep_in[0];
|
|
|
|
|
|
|
|
|
@ -369,31 +386,22 @@ USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev ,uint8_t epnum,
|
|
|
|
|
{
|
|
|
|
|
pep->rem_length -= pep->maxpacket;
|
|
|
|
|
|
|
|
|
|
USBD_CtlContinueSendData (pdev,
|
|
|
|
|
pdata,
|
|
|
|
|
pep->rem_length);
|
|
|
|
|
USBD_CtlContinueSendData (pdev, pdata, (uint16_t)pep->rem_length);
|
|
|
|
|
|
|
|
|
|
/* Prepare endpoint for premature end of transfer */
|
|
|
|
|
USBD_LL_PrepareReceive (pdev,
|
|
|
|
|
0,
|
|
|
|
|
NULL,
|
|
|
|
|
0);
|
|
|
|
|
USBD_LL_PrepareReceive (pdev, 0U, NULL, 0U);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{ /* last packet is MPS multiple, so send ZLP packet */
|
|
|
|
|
if((pep->total_length % pep->maxpacket == 0) &&
|
|
|
|
|
if((pep->total_length % pep->maxpacket == 0U) &&
|
|
|
|
|
(pep->total_length >= pep->maxpacket) &&
|
|
|
|
|
(pep->total_length < pdev->ep0_data_len))
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
USBD_CtlContinueSendData(pdev , NULL, 0);
|
|
|
|
|
pdev->ep0_data_len = 0;
|
|
|
|
|
USBD_CtlContinueSendData(pdev, NULL, 0U);
|
|
|
|
|
pdev->ep0_data_len = 0U;
|
|
|
|
|
|
|
|
|
|
/* Prepare endpoint for premature end of transfer */
|
|
|
|
|
USBD_LL_PrepareReceive (pdev,
|
|
|
|
|
0,
|
|
|
|
|
NULL,
|
|
|
|
|
0);
|
|
|
|
|
USBD_LL_PrepareReceive (pdev, 0U, NULL, 0U);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
@ -402,14 +410,24 @@ USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev ,uint8_t epnum,
|
|
|
|
|
{
|
|
|
|
|
pdev->pClass->EP0_TxSent(pdev);
|
|
|
|
|
}
|
|
|
|
|
USBD_LL_StallEP(pdev, 0x80U);
|
|
|
|
|
USBD_CtlReceiveStatus(pdev);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (pdev->dev_test_mode == 1)
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if ((pdev->ep0_state == USBD_EP0_STATUS_IN) ||
|
|
|
|
|
(pdev->ep0_state == USBD_EP0_IDLE))
|
|
|
|
|
{
|
|
|
|
|
USBD_LL_StallEP(pdev, 0x80U);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pdev->dev_test_mode == 1U)
|
|
|
|
|
{
|
|
|
|
|
USBD_RunTestMode(pdev);
|
|
|
|
|
pdev->dev_test_mode = 0;
|
|
|
|
|
pdev->dev_test_mode = 0U;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if((pdev->pClass->DataIn != NULL) &&
|
|
|
|
@ -417,6 +435,12 @@ USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev ,uint8_t epnum,
|
|
|
|
|
{
|
|
|
|
|
pdev->pClass->DataIn(pdev, epnum);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* should never be in this condition */
|
|
|
|
|
return USBD_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return USBD_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -430,33 +454,30 @@ USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev ,uint8_t epnum,
|
|
|
|
|
USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev)
|
|
|
|
|
{
|
|
|
|
|
/* Open EP0 OUT */
|
|
|
|
|
USBD_LL_OpenEP(pdev,
|
|
|
|
|
0x00,
|
|
|
|
|
USBD_EP_TYPE_CTRL,
|
|
|
|
|
USB_MAX_EP0_SIZE);
|
|
|
|
|
USBD_LL_OpenEP(pdev, 0x00U, USBD_EP_TYPE_CTRL, USB_MAX_EP0_SIZE);
|
|
|
|
|
pdev->ep_out[0x00U & 0xFU].is_used = 1U;
|
|
|
|
|
|
|
|
|
|
pdev->ep_out[0].maxpacket = USB_MAX_EP0_SIZE;
|
|
|
|
|
|
|
|
|
|
/* Open EP0 IN */
|
|
|
|
|
USBD_LL_OpenEP(pdev,
|
|
|
|
|
0x80,
|
|
|
|
|
USBD_EP_TYPE_CTRL,
|
|
|
|
|
USB_MAX_EP0_SIZE);
|
|
|
|
|
USBD_LL_OpenEP(pdev, 0x80U, USBD_EP_TYPE_CTRL, USB_MAX_EP0_SIZE);
|
|
|
|
|
pdev->ep_in[0x80U & 0xFU].is_used = 1U;
|
|
|
|
|
|
|
|
|
|
pdev->ep_in[0].maxpacket = USB_MAX_EP0_SIZE;
|
|
|
|
|
/* Upon Reset call user call back */
|
|
|
|
|
pdev->dev_state = USBD_STATE_DEFAULT;
|
|
|
|
|
pdev->ep0_state = USBD_EP0_IDLE;
|
|
|
|
|
pdev->dev_config= 0U;
|
|
|
|
|
pdev->dev_remote_wakeup = 0U;
|
|
|
|
|
|
|
|
|
|
if (pdev->pClassData)
|
|
|
|
|
pdev->pClass->DeInit(pdev, pdev->dev_config);
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
pdev->pClass->DeInit(pdev, (uint8_t)pdev->dev_config);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return USBD_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief USBD_LL_Reset
|
|
|
|
|
* Handle Reset event
|
|
|
|
@ -523,6 +544,10 @@ USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev)
|
|
|
|
|
*/
|
|
|
|
|
USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum)
|
|
|
|
|
{
|
|
|
|
|
/* Prevent unused arguments compilation warning */
|
|
|
|
|
UNUSED(pdev);
|
|
|
|
|
UNUSED(epnum);
|
|
|
|
|
|
|
|
|
|
return USBD_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -534,6 +559,10 @@ USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t ep
|
|
|
|
|
*/
|
|
|
|
|
USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum)
|
|
|
|
|
{
|
|
|
|
|
/* Prevent unused arguments compilation warning */
|
|
|
|
|
UNUSED(pdev);
|
|
|
|
|
UNUSED(epnum);
|
|
|
|
|
|
|
|
|
|
return USBD_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -545,6 +574,9 @@ USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev, uint8_t e
|
|
|
|
|
*/
|
|
|
|
|
USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev)
|
|
|
|
|
{
|
|
|
|
|
/* Prevent unused argument compilation warning */
|
|
|
|
|
UNUSED(pdev);
|
|
|
|
|
|
|
|
|
|
return USBD_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -558,7 +590,7 @@ USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev)
|
|
|
|
|
{
|
|
|
|
|
/* Free Class Resources */
|
|
|
|
|
pdev->dev_state = USBD_STATE_DEFAULT;
|
|
|
|
|
pdev->pClass->DeInit(pdev, pdev->dev_config);
|
|
|
|
|
pdev->pClass->DeInit(pdev, (uint8_t)pdev->dev_config);
|
|
|
|
|
|
|
|
|
|
return USBD_OK;
|
|
|
|
|
}
|
|
|
|
|