/** ****************************************************************************** * @file USBD_COMP.c * @author DB4PLE * @version V1.0.0 * @date 11-December-2015 * @brief This file provides the composite core functions. * * ****************************************************************************** * @attention * *

© COPYRIGHT 2015 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 #include "usbd_desc.h" #include "usbd_ctlreq.h" #include "uhsdr_board.h" /** @addtogroup STM32_USB_DEVICE_LIBRARY * @{ */ /** @defgroup USBD_COMP * @brief usbd core module * @{ */ /** @defgroup USBD_COMP_Private_TypesDefinitions * @{ */ /** * @} */ /** @defgroup USBD_COMP_Private_Defines * @{ */ /** * @} */ /** @defgroup USBD_COMP_Private_Macros * @{ */ /** * @} */ /** @defgroup USBD_COMP_Private_FunctionPrototypes * @{ */ static uint8_t USBD_COMP_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx); static uint8_t USBD_COMP_DeInit (USBD_HandleTypeDef *pdev, uint8_t cfgidx); static uint8_t USBD_COMP_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); static uint8_t *USBD_COMP_GetCfgDesc (uint16_t *length); static uint8_t *USBD_COMP_GetDeviceQualifierDesc (uint16_t *length); static uint8_t USBD_COMP_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum); static uint8_t USBD_COMP_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum); static uint8_t USBD_COMP_EP0_RxReady (USBD_HandleTypeDef *pdev); static uint8_t USBD_COMP_EP0_TxReady (USBD_HandleTypeDef *pdev); static uint8_t USBD_COMP_SOF (USBD_HandleTypeDef *pdev); static uint8_t USBD_COMP_IsoINIncomplete (USBD_HandleTypeDef *pdev, uint8_t epnum); static uint8_t USBD_COMP_IsoOutIncomplete (USBD_HandleTypeDef *pdev, uint8_t epnum); /** * @} */ /** @defgroup USBD_COMP_Private_Variables * @{ */ USBD_ClassTypeDef USBD_COMP = { USBD_COMP_Init, USBD_COMP_DeInit, USBD_COMP_Setup, USBD_COMP_EP0_TxReady, USBD_COMP_EP0_RxReady, USBD_COMP_DataIn, USBD_COMP_DataOut, USBD_COMP_SOF, USBD_COMP_IsoINIncomplete, USBD_COMP_IsoOutIncomplete, USBD_COMP_GetCfgDesc, USBD_COMP_GetCfgDesc, USBD_COMP_GetCfgDesc, USBD_COMP_GetDeviceQualifierDesc, }; USBD_COMP_ItfTypeDef USBD_COMP_fops_FS; /* USB Standard Device Descriptor */ __ALIGN_BEGIN static uint8_t USBD_COMP_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END= { USB_LEN_DEV_QUALIFIER_DESC, USB_DESC_TYPE_DEVICE_QUALIFIER, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, }; /** * @} */ /** @defgroup USBD_COMP_Private_Functions * @{ */ /** * @brief USBD_COMP_Init * Initialize the AUDIO interface * @param pdev: device instance * @param cfgidx: Configuration index * @retval status */ static inline void switchToClass(USBD_HandleTypeDef *pdev,USBD_ClassCompInfo* class) { pdev->pClassData = class->classData; pdev->pUserData = class->userData; } static inline void saveClass(USBD_HandleTypeDef *pdev,USBD_ClassCompInfo* class) { class->classData = pdev->pClassData; class->userData = pdev->pUserData; } static uint8_t USBD_COMP_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx) { uint8_t retval = USBD_OK; for (int i = 0; i < CLASS_NUM && retval == USBD_OK; i++) { switchToClass(pdev,&dev_instance[i]); retval = dev_instance[i].class->Init(pdev,cfgidx); saveClass(pdev,&dev_instance[i]); } return retval; } /** * @brief USBD_COMP_Init * DeInitialize the AUDIO layer * @param pdev: device instance * @param cfgidx: Configuration index * @retval status */ static uint8_t USBD_COMP_DeInit (USBD_HandleTypeDef *pdev, uint8_t cfgidx) { uint8_t retval = USBD_OK; for (int i = 0; i < CLASS_NUM && retval == USBD_OK; i++) { switchToClass(pdev,&dev_instance[i]); retval = dev_instance[i].class->DeInit(pdev,cfgidx); saveClass(pdev,&dev_instance[i]); } return retval; } /** * @brief USBD_COMP_Setup * Handle the AUDIO specific requests * @param pdev: instance * @param req: usb requests * @retval status */ static uint8_t* USBD_COMP_FindDescriptor(uint8_t desc_type) { uint8_t* retval = NULL; uint16_t desc_len; uint8_t* desc_ptr = USBD_COMP_GetCfgDesc(&desc_len); for (int32_t i = 0; i < desc_len; i += desc_ptr[i]) { if (desc_ptr[i+1] == desc_type) { retval = &desc_ptr[i]; break; } } return retval; } static uint8_t USBD_COMP_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) { uint16_t len; uint8_t *pbuf; uint8_t ret = USBD_OK; uint8_t done = 0; switch (req->bmRequest & USB_REQ_TYPE_MASK) { case USB_REQ_TYPE_CLASS : switch(req->bmRequest & USB_REQ_RECIPIENT_MASK) { case USB_REQ_RECIPIENT_INTERFACE: for (int i = 0; i < CLASS_NUM; i++) { uint8_t interface = req->wValue >> 8; if (interface >= dev_instance[i].minIf && interface <= dev_instance[i].maxIf) { switchToClass(pdev,&dev_instance[i]); ret = dev_instance[i].class->Setup(pdev,req); done = 1; break; } } break; default: break; } if (done != 1) { USBD_CtlError (pdev, req); ret = USBD_FAIL; } break; case USB_REQ_TYPE_STANDARD: switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: { pbuf = USBD_COMP_FindDescriptor(req->wValue >> 8); if(pbuf != NULL) { len = MIN(pbuf[0], req->wLength); USBD_CtlSendData (pdev, pbuf, len); } } break; case USB_REQ_GET_INTERFACE : case USB_REQ_SET_INTERFACE : if ((uint8_t)(req->wIndex) <= USBD_MAX_NUM_INTERFACES) { for (int i = 0; i < CLASS_NUM; i++) { if (req->wIndex >= dev_instance[i].minIf && req->wIndex <= dev_instance[i].maxIf) { switchToClass(pdev,&dev_instance[i]); ret = dev_instance[i].class->Setup(pdev,req); done = 1; break; } } } else { /* Call the error management function (command will be nacked */ USBD_CtlError (pdev, req); } break; default: USBD_CtlError (pdev, req); ret = USBD_FAIL; } } return ret; } /** * @brief USBD_COMP_GetCfgDesc * return configuration descriptor * @param speed : current device speed * @param length : pointer data length * @retval pointer to descriptor buffer */ static uint8_t *USBD_COMP_GetCfgDesc (uint16_t *length) { *length = sizeof (USBD_COMP_CfgDesc); return USBD_COMP_CfgDesc; } /** * @brief USBD_COMP_DataIn * handle data IN Stage * @param pdev: device instance * @param epnum: endpoint index * @retval status */ static uint8_t USBD_COMP_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum) { uint8_t retval = USBD_OK; if (epnum <= USBD_MAX_EP) { uint8_t classIdx = usbdEpMap.in[epnum]; if (classIdx < CLASS_NUM) { if (dev_instance[classIdx].class->DataIn != NULL) { switchToClass(pdev,&dev_instance[classIdx]); retval = dev_instance[classIdx].class->DataIn(pdev,epnum); } } } return retval; } /** * @brief USBD_COMP_EP0_RxReady * handle EP0 Rx Ready event * @param pdev: device instance * @retval status */ static uint8_t USBD_COMP_EP0_RxReady (USBD_HandleTypeDef *pdev) { uint8_t retval = USBD_OK; for (int i = 0; i < CLASS_NUM; i++) { if (dev_instance[i].class->EP0_RxReady != NULL) { switchToClass(pdev,&dev_instance[i]); retval = dev_instance[i].class->EP0_RxReady(pdev); } if (retval != USBD_OK) { break; } } return retval; } /** * @brief USBD_COMP_EP0_TxReady * handle EP0 TRx Ready event * @param pdev: device instance * @retval status */ static uint8_t USBD_COMP_EP0_TxReady (USBD_HandleTypeDef *pdev) { uint8_t retval = USBD_OK; for (int i = 0; i < CLASS_NUM; i++) { if (dev_instance[i].class->EP0_TxSent != NULL) { switchToClass(pdev,&dev_instance[i]); retval = dev_instance[i].class->EP0_TxSent(pdev); } if (retval != USBD_OK) { break; } } return retval; } /** * @brief USBD_COMP_SOF * handle SOF event * @param pdev: device instance * @retval status */ static uint8_t USBD_COMP_SOF (USBD_HandleTypeDef *pdev) { uint8_t retval = USBD_OK; for (int i = 0; i < CLASS_NUM; i++) { if (dev_instance[i].class->SOF != NULL) { switchToClass(pdev,&dev_instance[i]); retval = dev_instance[i].class->SOF(pdev); if (retval != USBD_OK) { break; } } } return retval; } /** * @brief USBD_COMP_IsoINIncomplete * handle data ISO IN Incomplete event * @param pdev: device instance * @param epnum: endpoint index * @retval status */ static uint8_t USBD_COMP_IsoINIncomplete (USBD_HandleTypeDef *pdev, uint8_t epnum) { uint8_t retval = USBD_OK; for (int i = 0; i < CLASS_NUM; i++) { if (dev_instance[i].class->IsoINIncomplete != NULL) { switchToClass(pdev,&dev_instance[i]); retval = dev_instance[i].class->IsoINIncomplete(pdev, epnum); if (retval != USBD_OK) { break; } } } return retval; } /** * @brief USBD_COMP_IsoOutIncomplete * handle data ISO OUT Incomplete event * @param pdev: device instance * @param epnum: endpoint index * @retval status */ static uint8_t USBD_COMP_IsoOutIncomplete (USBD_HandleTypeDef *pdev, uint8_t epnum) { uint8_t retval = USBD_OK; for (int i = 0; i < CLASS_NUM; i++) { if (dev_instance[i].class->IsoOUTIncomplete != NULL) { switchToClass(pdev,&dev_instance[i]); retval = dev_instance[i].class->IsoOUTIncomplete(pdev, epnum); if (retval != USBD_OK) { break; } } } return retval; } /** * @brief USBD_COMP_DataOut * handle data OUT Stage * @param pdev: device instance * @param epnum: endpoint index * @retval status */ static uint8_t USBD_COMP_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum) { uint8_t retval = USBD_OK; if (epnum <= USBD_MAX_EP) { uint8_t classIdx = usbdEpMap.out[epnum]; if (classIdx < CLASS_NUM) { if (dev_instance[classIdx].class->DataOut != NULL) { switchToClass(pdev,&dev_instance[classIdx]); retval = dev_instance[classIdx].class->DataOut(pdev,epnum); } } } return retval; } /** * @brief DeviceQualifierDescriptor * return Device Qualifier descriptor * @param length : pointer data length * @retval pointer to descriptor buffer */ static uint8_t *USBD_COMP_GetDeviceQualifierDesc (uint16_t *length) { *length = sizeof (USBD_COMP_DeviceQualifierDesc); return USBD_COMP_DeviceQualifierDesc; } /** * @brief USBD_COMP_RegisterInterface * @param fops: Audio interface callback * @retval status */ uint8_t USBD_COMP_RegisterInterface (USBD_HandleTypeDef *pdev, USBD_COMP_ItfTypeDef *fops) { if(fops != NULL) { pdev->pUserData= fops; } return 0; } /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/