diff --git a/.gitignore b/.gitignore index 0af1cba..7ef5dd5 100644 --- a/.gitignore +++ b/.gitignore @@ -51,8 +51,6 @@ Module.symvers Mkfile.old dkms.conf -USBD_Test/ -Test/ Files/ Debug/ debug/ diff --git a/I-CUBE-USBD-COMPOSITE/AL94.I-CUBE-USBD-COMPOSITE.1.0.3.pack b/I-CUBE-USBD-COMPOSITE/AL94.I-CUBE-USBD-COMPOSITE.1.0.3.pack index 4776688..1d74922 100644 Binary files a/I-CUBE-USBD-COMPOSITE/AL94.I-CUBE-USBD-COMPOSITE.1.0.3.pack and b/I-CUBE-USBD-COMPOSITE/AL94.I-CUBE-USBD-COMPOSITE.1.0.3.pack differ diff --git a/USBD_Test/Composite/AL94.I-CUBE-USBD-COMPOSITE_conf.h b/USBD_Test/Composite/AL94.I-CUBE-USBD-COMPOSITE_conf.h new file mode 100644 index 0000000..03dd3a2 --- /dev/null +++ b/USBD_Test/Composite/AL94.I-CUBE-USBD-COMPOSITE_conf.h @@ -0,0 +1,87 @@ +/** + ****************************************************************************** + * File Name : AL94.I-CUBE-USBD-COMPOSITE_conf.h + * Description : This file provides code for the configuration + * of the AL94.I-CUBE-USBD-COMPOSITE_conf.h instances. + ****************************************************************************** + * @attention + * + * Copyright (c) 2022 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __AL94__I_CUBE_USBD_COMPOSITE_CONF__H__ +#define __AL94__I_CUBE_USBD_COMPOSITE_CONF__H__ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ + +/** + MiddleWare name : AL94.I-CUBE-USBD-COMPOSITE.1.0.3 + MiddleWare fileName : AL94.I-CUBE-USBD-COMPOSITE_conf.h + MiddleWare version : +*/ +/*---------- _USBD_USE_HS -----------*/ +#define _USBD_USE_HS true + +/*---------- _USBD_USE_CDC_ACM -----------*/ +#define _USBD_USE_CDC_ACM true + +/*---------- _USBD_CDC_ACM_COUNT -----------*/ +#define _USBD_CDC_ACM_COUNT 1 + +/*---------- _USBD_USE_CDC_RNDIS -----------*/ +#define _USBD_USE_CDC_RNDIS true + +/*---------- _USBD_USE_CDC_ECM -----------*/ +#define _USBD_USE_CDC_ECM true + +/*---------- _USBD_USE_HID_MOUSE -----------*/ +#define _USBD_USE_HID_MOUSE true + +/*---------- _USBD_USE_HID_KEYBOARD -----------*/ +#define _USBD_USE_HID_KEYBOARD true + +/*---------- _USBD_USE_HID_CUSTOM -----------*/ +#define _USBD_USE_HID_CUSTOM true + +/*---------- _USBD_USE_UAC_MIC -----------*/ +#define _USBD_USE_UAC_MIC true + +/*---------- _USBD_USE_UAC_SPKR -----------*/ +#define _USBD_USE_UAC_SPKR true + +/*---------- _USBD_USE_UVC -----------*/ +#define _USBD_USE_UVC true + +/*---------- _USBD_USE_MSC -----------*/ +#define _USBD_USE_MSC true + +/*---------- _USBD_USE_DFU -----------*/ +#define _USBD_USE_DFU true + +/*---------- _USBD_USE_PRNTR -----------*/ +#define _USBD_USE_PRNTR true + +/*---------- _STM32F1_DEVICE -----------*/ +#define _STM32F1_DEVICE false + +#ifdef __cplusplus +} +#endif +#endif /*__ AL94__I_CUBE_USBD_COMPOSITE_CONF__H_H */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Drivers/CMSIS/Device/ST/STM32H7xx/LICENSE.txt b/USBD_Test/Drivers/CMSIS/Device/ST/STM32H7xx/LICENSE.txt new file mode 100644 index 0000000..872e82b --- /dev/null +++ b/USBD_Test/Drivers/CMSIS/Device/ST/STM32H7xx/LICENSE.txt @@ -0,0 +1,6 @@ +This software component is provided to you as part of a software package and +applicable license terms are in the Package_license file. If you received this +software component outside of a package or without applicable license terms, +the terms of the Apache-2.0 license shall apply. +You may obtain a copy of the Apache-2.0 at: +https://opensource.org/licenses/Apache-2.0 diff --git a/USBD_Test/Drivers/CMSIS/Device/ST/STM32H7xx/License.md b/USBD_Test/Drivers/CMSIS/Device/ST/STM32H7xx/License.md new file mode 100644 index 0000000..008472d --- /dev/null +++ b/USBD_Test/Drivers/CMSIS/Device/ST/STM32H7xx/License.md @@ -0,0 +1 @@ +License.md file kept for legacy purpose \ No newline at end of file diff --git a/USBD_Test/Drivers/CMSIS/LICENSE.txt b/USBD_Test/Drivers/CMSIS/LICENSE.txt new file mode 100644 index 0000000..8dada3e --- /dev/null +++ b/USBD_Test/Drivers/CMSIS/LICENSE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + + 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. diff --git a/USBD_Test/Drivers/STM32H7xx_HAL_Driver/LICENSE.txt b/USBD_Test/Drivers/STM32H7xx_HAL_Driver/LICENSE.txt new file mode 100644 index 0000000..3edc4d1 --- /dev/null +++ b/USBD_Test/Drivers/STM32H7xx_HAL_Driver/LICENSE.txt @@ -0,0 +1,6 @@ +This software component is provided to you as part of a software package and +applicable license terms are in the Package_license file. If you received this +software component outside of a package or without applicable license terms, +the terms of the BSD-3-Clause license shall apply. +You may obtain a copy of the BSD-3-Clause at: +https://opensource.org/licenses/BSD-3-Clause diff --git a/USBD_Test/Drivers/STM32H7xx_HAL_Driver/License.md b/USBD_Test/Drivers/STM32H7xx_HAL_Driver/License.md new file mode 100644 index 0000000..008472d --- /dev/null +++ b/USBD_Test/Drivers/STM32H7xx_HAL_Driver/License.md @@ -0,0 +1 @@ +License.md file kept for legacy purpose \ No newline at end of file diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_audio_mic_if.c b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_audio_mic_if.c new file mode 100644 index 0000000..f94fd86 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_audio_mic_if.c @@ -0,0 +1,174 @@ +/** + ****************************************************************************** + * @file usbd_audio_if.c + * @author SRA - Central Labs + * @version v1.1.0 + * @date 03-Apr-2020 + * @brief USB Device Audio interface file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_audio_mic_if.h" + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +static int8_t Audio_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr); +static int8_t Audio_DeInit(uint32_t options); +static int8_t Audio_Record(void); +static int8_t Audio_VolumeCtl(int16_t Volume); +static int8_t Audio_MuteCtl(uint8_t cmd); +static int8_t Audio_Stop(void); +static int8_t Audio_Pause(void); +static int8_t Audio_Resume(void); +static int8_t Audio_CommandMgr(uint8_t cmd); + +/* Private variables ---------------------------------------------------------*/ +extern USBD_HandleTypeDef hUsbDeviceFS; + +USBD_AUDIO_MIC_ItfTypeDef USBD_AUDIO_MIC_fops_FS = { + Audio_Init, + Audio_DeInit, + Audio_Record, + Audio_VolumeCtl, + Audio_MuteCtl, + Audio_Stop, + Audio_Pause, + Audio_Resume, + Audio_CommandMgr, +}; + +/* Private functions ---------------------------------------------------------*/ +/* This table maps the audio device class setting in 1/256 dB to a +* linear 0-64 scaling used in pdm_filter.c. It is computed as +* 256*20*log10(index/64). */ +const int16_t vol_table[65] = +{ 0x8000, 0xDBE0, 0xE1E6, 0xE56B, 0xE7EB, 0xE9DB, 0xEB70, 0xECC7, +0xEDF0, 0xEEF6, 0xEFE0, 0xF0B4, 0xF176, 0xF228, 0xF2CD, 0xF366, +0xF3F5, 0xF47C, 0xF4FB, 0xF574, 0xF5E6, 0xF652, 0xF6BA, 0xF71C, +0xF778, 0xF7D6, 0xF82D, 0xF881, 0xF8D2, 0xF920, 0xF96B, 0xF9B4, +0xF9FB, 0xFA3F, 0xFA82, 0xFAC2, 0xFB01, 0xFB3E, 0xFB79, 0xFBB3, +0xFBEB, 0xFC22, 0xFC57, 0xFC8C, 0xFCBF, 0xFCF1, 0xFD22, 0xFD51, +0xFD80, 0xFDAE, 0xFDDB, 0xFE07, 0xFE32, 0xFE5D, 0xFE86, 0xFEAF, +0xFED7, 0xFF00, 0xFF25, 0xFF4B, 0xFF70, 0xFF95, 0xFFB9, 0xFFD0, +0x0000 }; + + +/** +* @brief Initializes the AUDIO media low layer. +* @param AudioFreq: Audio frequency used to play the audio stream. +* @param BitRes: desired bit resolution +* @param ChnlNbr: number of channel to be configured +* @retval BSP_ERROR_NONE in case of success, AUDIO_ERROR otherwise +*/ +static int8_t Audio_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) +{ + return USBD_OK; +} + +/** +* @brief De-Initializes the AUDIO media low layer. +* @param options: Reserved for future use +* @retval BSP_ERROR_NONE in case of success, AUDIO_ERROR otherwise +*/ +static int8_t Audio_DeInit(uint32_t options) +{ + return USBD_OK; +} + +/** +* @brief Start audio recording engine +* @retval BSP_ERROR_NONE in case of success, AUDIO_ERROR otherwise +*/ +static int8_t Audio_Record(void) +{ + return USBD_OK; +} + +/** +* @brief Controls AUDIO Volume. +* @param vol: Volume level +* @retval BSP_ERROR_NONE in case of success, AUDIO_ERROR otherwise +*/ +static int8_t Audio_VolumeCtl(int16_t Volume) +{ + /* Call low layer volume setting function */ + uint32_t j = 0; + + /* Find the setting nearest to the desired setting */ + while(j<64 && abs(Volume-vol_table[j]) > abs(Volume-vol_table[j+1])) + { + j++; + } + /** TODO */ + return USBD_OK; +} + +/** +* @brief Controls AUDIO Mute. +* @param cmd: Command opcode +* @retval BSP_ERROR_NONE in case of success, AUDIO_ERROR otherwise +*/ +static int8_t Audio_MuteCtl(uint8_t cmd) +{ + return USBD_OK; +} + + +/** +* @brief Stops audio acquisition +* @param none +* @retval BSP_ERROR_NONE in case of success, AUDIO_ERROR otherwise +*/ +static int8_t Audio_Stop(void) +{ + return USBD_OK; +} + +/** +* @brief Pauses audio acquisition +* @param none +* @retval BSP_ERROR_NONE in case of success, AUDIO_ERROR otherwise +*/ + +static int8_t Audio_Pause(void) +{ + return USBD_OK; +} + + +/** +* @brief Resumes audio acquisition +* @param none +* @retval BSP_ERROR_NONE in case of success, AUDIO_ERROR otherwise +*/ +static int8_t Audio_Resume(void) +{ + return USBD_OK; +} + +/** +* @brief Manages command from usb +* @param None +* @retval BSP_ERROR_NONE in case of success, AUDIO_ERROR otherwise +*/ + +static int8_t Audio_CommandMgr(uint8_t cmd) +{ + return USBD_OK; +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_audio_mic_if.h b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_audio_mic_if.h new file mode 100644 index 0000000..18ac72d --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_audio_mic_if.h @@ -0,0 +1,37 @@ +/** + ****************************************************************************** + * @file usbd_audio_if.h + * @author SRA - Central Labs + * @version v1.1.0 + * @date 03-Apr-2020 + * @brief Header for usbd_audio_if.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_AUDIO_IF_H +#define __USBD_AUDIO_IF_H + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_audio_mic.h" +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ + +extern USBD_AUDIO_MIC_ItfTypeDef USBD_AUDIO_MIC_fops_FS; + +#endif /* __USBD_AUDIO_IF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_audio_spkr_if.c b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_audio_spkr_if.c new file mode 100644 index 0000000..a601744 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_audio_spkr_if.c @@ -0,0 +1,290 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : usbd_audio_if.c + * @version : v1.0_Cube + * @brief : Generic media access layer. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + /* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_audio_spkr_if.h" + +/* USER CODE BEGIN INCLUDE */ +//#include "cs43l22.h" +/* USER CODE END INCLUDE */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE END PV */ + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @brief Usb device library. + * @{ + */ + +/** @addtogroup USBD_AUDIO_IF + * @{ + */ + +/** @defgroup USBD_AUDIO_IF_Private_TypesDefinitions USBD_AUDIO_IF_Private_TypesDefinitions + * @brief Private types. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_TYPES */ + +/* USER CODE END PRIVATE_TYPES */ + +/** + * @} + */ + +/** @defgroup USBD_AUDIO_IF_Private_Defines USBD_AUDIO_IF_Private_Defines + * @brief Private defines. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_DEFINES */ + +/* USER CODE END PRIVATE_DEFINES */ + +/** + * @} + */ + +/** @defgroup USBD_AUDIO_IF_Private_Macros USBD_AUDIO_IF_Private_Macros + * @brief Private macros. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_MACRO */ + +/* USER CODE END PRIVATE_MACRO */ + +/** + * @} + */ + +/** @defgroup USBD_AUDIO_IF_Private_Variables USBD_AUDIO_IF_Private_Variables + * @brief Private variables. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_VARIABLES */ + +/* USER CODE END PRIVATE_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_AUDIO_IF_Exported_Variables USBD_AUDIO_IF_Exported_Variables + * @brief Public variables. + * @{ + */ + +extern USBD_HandleTypeDef hUsbDevice; + +/* USER CODE BEGIN EXPORTED_VARIABLES */ + +/* USER CODE END EXPORTED_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_AUDIO_IF_Private_FunctionPrototypes USBD_AUDIO_IF_Private_FunctionPrototypes + * @brief Private functions declaration. + * @{ + */ + +static int8_t AUDIO_Init(uint32_t AudioFreq, uint32_t Volume, uint32_t options); +static int8_t AUDIO_DeInit(uint32_t options); +static int8_t AUDIO_AudioCmd(uint8_t* pbuf, uint32_t size, uint8_t cmd); +static int8_t AUDIO_VolumeCtl(uint8_t vol); +static int8_t AUDIO_MuteCtl(uint8_t cmd); +static int8_t AUDIO_PeriodicTC(uint8_t *pbuf, uint32_t size, uint8_t cmd); +static int8_t AUDIO_GetState(void); + +/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */ + +/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */ + +/** + * @} + */ + +USBD_AUDIO_SPKR_ItfTypeDef USBD_AUDIO_SPKR_fops = +{ + AUDIO_Init, + AUDIO_DeInit, + AUDIO_AudioCmd, + AUDIO_VolumeCtl, + AUDIO_MuteCtl, + AUDIO_PeriodicTC, + AUDIO_GetState, +}; + +/* Private functions ---------------------------------------------------------*/ +/** + * @brief Initializes the AUDIO media low layer over USB FS IP + * @param AudioFreq: Audio frequency used to play the audio stream. + * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) + * @param options: Reserved for future use + * @retval USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t AUDIO_Init(uint32_t AudioFreq, uint32_t Volume, uint32_t options) +{ + /* USER CODE BEGIN 0 */ + UNUSED(AudioFreq); + UNUSED(Volume); + UNUSED(options); + return (USBD_OK); + /* USER CODE END 0 */ +} + +/** + * @brief De-Initializes the AUDIO media low layer + * @param options: Reserved for future use + * @retval USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t AUDIO_DeInit(uint32_t options) +{ + /* USER CODE BEGIN 1 */ + UNUSED(options); + return (USBD_OK); + /* USER CODE END 1 */ +} + +/** + * @brief Handles AUDIO command. + * @param pbuf: Pointer to buffer of data to be sent + * @param size: Number of data to be sent (in bytes) + * @param cmd: Command opcode + * @retval USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t AUDIO_AudioCmd(uint8_t* pbuf, uint32_t size, uint8_t cmd) +{ + /* USER CODE BEGIN 2 */ + switch(cmd) + { + case AUDIO_CMD_START: + break; + + case AUDIO_CMD_PLAY: + break; + } + UNUSED(pbuf); + UNUSED(size); + UNUSED(cmd); + return (USBD_OK); + /* USER CODE END 2 */ +} + +/** + * @brief Controls AUDIO Volume. + * @param vol: volume level (0..100) + * @retval USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t AUDIO_VolumeCtl(uint8_t vol) +{ + /* USER CODE BEGIN 3 */ + UNUSED(vol); + //cs43l22_SetVolume(CS43L22_I2C_ADDRESS, vol); + return (USBD_OK); + /* USER CODE END 3 */ +} + +/** + * @brief Controls AUDIO Mute. + * @param cmd: command opcode + * @retval USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t AUDIO_MuteCtl(uint8_t cmd) +{ + /* USER CODE BEGIN 4 */ + UNUSED(cmd); + //cs43l22_SetMute(CS43L22_I2C_ADDRESS, cmd); + return (USBD_OK); + /* USER CODE END 4 */ +} + +/** + * @brief AUDIO_PeriodicT + * @param cmd: Command opcode + * @retval USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t AUDIO_PeriodicTC(uint8_t *pbuf, uint32_t size, uint8_t cmd) +{ + /* USER CODE BEGIN 5 */ + UNUSED(pbuf); + UNUSED(size); + UNUSED(cmd); + return (USBD_OK); + /* USER CODE END 5 */ +} + +/** + * @brief Gets AUDIO State. + * @retval USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t AUDIO_GetState(void) +{ + /* USER CODE BEGIN 6 */ + return (USBD_OK); + /* USER CODE END 6 */ +} + +/** + * @brief Manages the DMA full transfer complete event. + * @retval None + */ +void TransferComplete_CallBack(void) +{ + /* USER CODE BEGIN 7 */ + USBD_AUDIO_SPKR_Sync(&hUsbDevice, AUDIO_OFFSET_FULL); + /* USER CODE END 7 */ +} + +/** + * @brief Manages the DMA Half transfer complete event. + * @retval None + */ +void HalfTransfer_CallBack(void) +{ + /* USER CODE BEGIN 8 */ + USBD_AUDIO_SPKR_Sync(&hUsbDevice, AUDIO_OFFSET_HALF); + /* USER CODE END 8 */ +} + +/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */ + +/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_audio_spkr_if.h b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_audio_spkr_if.h new file mode 100644 index 0000000..12fab9c --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_audio_spkr_if.h @@ -0,0 +1,140 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : usbd_audio_if.h + * @version : v1.0_Cube + * @brief : Header for usbd_audio_if.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_AUDIO_SPKR_IF_H__ +#define __USBD_AUDIO_SPKR_IF_H__ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_audio_spkr.h" + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @brief For Usb device. + * @{ + */ + +/** @defgroup USBD_AUDIO_IF USBD_AUDIO_IF + * @brief Usb audio interface device module. + * @{ + */ + +/** @defgroup USBD_AUDIO_IF_Exported_Defines USBD_AUDIO_IF_Exported_Defines + * @brief Defines. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_DEFINES */ + +/* USER CODE END EXPORTED_DEFINES */ + +/** + * @} + */ + +/** @defgroup USBD_AUDIO_IF_Exported_Types USBD_AUDIO_IF_Exported_Types + * @brief Types. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_TYPES */ + +/* USER CODE END EXPORTED_TYPES */ + +/** + * @} + */ + +/** @defgroup USBD_AUDIO_IF_Exported_Macros USBD_AUDIO_IF_Exported_Macros + * @brief Aliases. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_MACRO */ + +/* USER CODE END EXPORTED_MACRO */ + +/** + * @} + */ + +/** @defgroup USBD_AUDIO_IF_Exported_Variables USBD_AUDIO_IF_Exported_Variables + * @brief Public variables. + * @{ + */ + +/** AUDIO_IF Interface callback. */ +extern USBD_AUDIO_SPKR_ItfTypeDef USBD_AUDIO_SPKR_fops; + +/* USER CODE BEGIN EXPORTED_VARIABLES */ + +/* USER CODE END EXPORTED_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_AUDIO_IF_Exported_FunctionsPrototype USBD_AUDIO_IF_Exported_FunctionsPrototype + * @brief Public functions declaration. + * @{ + */ + +/** + * @brief Manages the DMA full transfer complete event. + * @retval None + */ +void TransferComplete_CallBack_FS(void); + +/** + * @brief Manages the DMA half transfer complete event. + * @retval None + */ +void HalfTransfer_CallBack_FS(void); + +/* USER CODE BEGIN EXPORTED_FUNCTIONS */ + +/* USER CODE END EXPORTED_FUNCTIONS */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_AUDIO_SPKR_IF_H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_cdc_acm_if.c b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_cdc_acm_if.c new file mode 100644 index 0000000..ea7121c --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_cdc_acm_if.c @@ -0,0 +1,544 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : usbd_cdc_if.c + * @version : v2.0_Cube + * @brief : Usb device for Virtual Com Port. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_cdc_acm_if.h" + +/* USER CODE BEGIN INCLUDE */ +//#include "usart.h" +//#include "tim.h" +/* USER CODE END INCLUDE */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE END PV */ + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @brief Usb device library. + * @{ + */ + +/** @addtogroup USBD_CDC_IF + * @{ + */ + +/** @defgroup USBD_CDC_IF_Private_TypesDefinitions USBD_CDC_IF_Private_TypesDefinitions + * @brief Private types. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_TYPES */ + +/* USER CODE END PRIVATE_TYPES */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Private_Defines USBD_CDC_IF_Private_Defines + * @brief Private defines. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_DEFINES */ +/* USER CODE END PRIVATE_DEFINES */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Private_Macros USBD_CDC_IF_Private_Macros + * @brief Private macros. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_MACRO */ + +/* USER CODE END PRIVATE_MACRO */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Private_Variables USBD_CDC_IF_Private_Variables + * @brief Private variables. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_VARIABLES */ + +#define APP_RX_DATA_SIZE 128 +#define APP_TX_DATA_SIZE 128 + +/** RX buffer for USB */ +uint8_t RX_Buffer[NUMBER_OF_CDC][APP_RX_DATA_SIZE]; + +/** TX buffer for USB, RX buffer for UART */ +uint8_t TX_Buffer[NUMBER_OF_CDC][APP_TX_DATA_SIZE]; + +USBD_CDC_ACM_LineCodingTypeDef Line_Coding[NUMBER_OF_CDC]; + +uint32_t Write_Index[NUMBER_OF_CDC]; /* keep track of received data over UART */ +uint32_t Read_Index[NUMBER_OF_CDC]; /* keep track of sent data to USB */ + +/* USER CODE END PRIVATE_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Exported_Variables USBD_CDC_IF_Exported_Variables + * @brief Public variables. + * @{ + */ + +extern USBD_HandleTypeDef hUsbDevice; + +/* USER CODE BEGIN EXPORTED_VARIABLES */ + +/* USER CODE END EXPORTED_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Private_FunctionPrototypes USBD_CDC_IF_Private_FunctionPrototypes + * @brief Private functions declaration. + * @{ + */ + +static int8_t CDC_Init(uint8_t cdc_ch); +static int8_t CDC_DeInit(uint8_t cdc_ch); +static int8_t CDC_Control(uint8_t cdc_ch, uint8_t cmd, uint8_t *pbuf, uint16_t length); +static int8_t CDC_Receive(uint8_t cdc_ch, uint8_t *pbuf, uint32_t *Len); +static int8_t CDC_TransmitCplt(uint8_t cdc_ch, uint8_t *Buf, uint32_t *Len, uint8_t epnum); + +/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */ +//UART_HandleTypeDef *CDC_CH_To_UART_Handle(uint8_t cdc_ch) +//{ +// UART_HandleTypeDef *handle = NULL; +// +// if (cdc_ch == 0) +// { +// handle = &huart1; +// } +//#if (0) +// else if (cdc_ch == 1) +// { +// handle = &huart2; +// } +// else if (cdc_ch == 2) +// { +// handle = &huart3; +// } +//#endif +// return handle; +//} +// +//uint8_t UART_Handle_TO_CDC_CH(UART_HandleTypeDef *handle) +//{ +// uint8_t cdc_ch = 0; +// +// if (handle == &huart1) +// { +// cdc_ch = 0; +// } +//#if (0) +// else if (handle == &huart2) +// { +// cdc_ch = 1; +// } +// else if (handle == &huart3) +// { +// cdc_ch = 2; +// } +//#endif +// return cdc_ch; +//} +// +//void Change_UART_Setting(uint8_t cdc_ch) +//{ +// UART_HandleTypeDef *handle = CDC_CH_To_UART_Handle(cdc_ch); +// +// if (HAL_UART_DeInit(handle) != HAL_OK) +// { +// /* Initialization Error */ +// Error_Handler(); +// } +// /* set the Stop bit */ +// switch (Line_Coding[cdc_ch].format) +// { +// case 0: +// handle->Init.StopBits = UART_STOPBITS_1; +// break; +// case 2: +// handle->Init.StopBits = UART_STOPBITS_2; +// break; +// default: +// handle->Init.StopBits = UART_STOPBITS_1; +// break; +// } +// +// /* set the parity bit*/ +// switch (Line_Coding[cdc_ch].paritytype) +// { +// case 0: +// handle->Init.Parity = UART_PARITY_NONE; +// break; +// case 1: +// handle->Init.Parity = UART_PARITY_ODD; +// break; +// case 2: +// handle->Init.Parity = UART_PARITY_EVEN; +// break; +// default: +// handle->Init.Parity = UART_PARITY_NONE; +// break; +// } +// +// /*set the data type : only 8bits and 9bits is supported */ +// switch (Line_Coding[cdc_ch].datatype) +// { +// case 0x07: +// /* With this configuration a parity (Even or Odd) must be set */ +// handle->Init.WordLength = UART_WORDLENGTH_8B; +// break; +// case 0x08: +// if (handle->Init.Parity == UART_PARITY_NONE) +// { +// handle->Init.WordLength = UART_WORDLENGTH_8B; +// } +// else +// { +// handle->Init.WordLength = UART_WORDLENGTH_9B; +// } +// +// break; +// default: +// handle->Init.WordLength = UART_WORDLENGTH_8B; +// break; +// } +// +// if (Line_Coding[cdc_ch].bitrate == 0) +// { +// Line_Coding[cdc_ch].bitrate = 115200; +// } +// +// handle->Init.BaudRate = Line_Coding[cdc_ch].bitrate; +// handle->Init.HwFlowCtl = UART_HWCONTROL_NONE; +// handle->Init.Mode = UART_MODE_TX_RX; +// handle->Init.OverSampling = UART_OVERSAMPLING_16; +// +// if (HAL_UART_Init(handle) != HAL_OK) +// { +// /* Initialization Error */ +// Error_Handler(); +// } +// +// /** rx for uart and tx buffer of usb */ +// if (HAL_UART_Receive_IT(handle, TX_Buffer[cdc_ch], 1) != HAL_OK) +// { +// /* Transfer error in reception process */ +// Error_Handler(); +// } +//} +/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */ + +/** + * @} + */ + +USBD_CDC_ACM_ItfTypeDef USBD_CDC_ACM_fops = {CDC_Init, + CDC_DeInit, + CDC_Control, + CDC_Receive, + CDC_TransmitCplt}; + +/* Private functions ---------------------------------------------------------*/ +/** + * @brief Initializes the CDC media low layer over the FS USB IP + * @retval USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_Init(uint8_t cdc_ch) +{ + /* USER CODE BEGIN 3 */ + + /* ##-1- Set Application Buffers */ + USBD_CDC_SetRxBuffer(cdc_ch, &hUsbDevice, RX_Buffer[cdc_ch]); + + // /*##-2- Start the TIM Base generation in interrupt mode ####################*/ + // /* Start Channel1 */ + // if (HAL_TIM_Base_Start_IT(&htim4) != HAL_OK) + // { + // /* Starting Error */ + // Error_Handler(); + // } + + return (USBD_OK); + /* USER CODE END 3 */ +} + +/** + * @brief DeInitializes the CDC media low layer + * @retval USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_DeInit(uint8_t cdc_ch) +{ + /* USER CODE BEGIN 4 */ + /* DeInitialize the UART peripheral */ + // if (HAL_UART_DeInit(CDC_CH_To_UART_Handle(cdc_ch)) != HAL_OK) + // { + // /* Initialization Error */ + // Error_Handler(); + // } + return (USBD_OK); + /* USER CODE END 4 */ +} + +/** + * @brief Manage the CDC class requests + * @param cmd: Command code + * @param pbuf: Buffer containing command data (request parameters) + * @param length: Number of data to be sent (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_Control(uint8_t cdc_ch, uint8_t cmd, uint8_t *pbuf, uint16_t length) +{ + /* USER CODE BEGIN 5 */ + switch (cmd) + { + case CDC_SEND_ENCAPSULATED_COMMAND: + + break; + + case CDC_GET_ENCAPSULATED_RESPONSE: + + break; + + case CDC_SET_COMM_FEATURE: + + break; + + case CDC_GET_COMM_FEATURE: + + break; + + case CDC_CLEAR_COMM_FEATURE: + + break; + + /*******************************************************************************/ + /* Line Coding Structure */ + /*-----------------------------------------------------------------------------*/ + /* Offset | Field | Size | Value | Description */ + /* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/ + /* 4 | bCharFormat | 1 | Number | Stop bits */ + /* 0 - 1 Stop bit */ + /* 1 - 1.5 Stop bits */ + /* 2 - 2 Stop bits */ + /* 5 | bParityType | 1 | Number | Parity */ + /* 0 - None */ + /* 1 - Odd */ + /* 2 - Even */ + /* 3 - Mark */ + /* 4 - Space */ + /* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */ + /*******************************************************************************/ + case CDC_SET_LINE_CODING: + Line_Coding[cdc_ch].bitrate = (uint32_t)(pbuf[0] | (pbuf[1] << 8) | + (pbuf[2] << 16) | (pbuf[3] << 24)); + Line_Coding[cdc_ch].format = pbuf[4]; + Line_Coding[cdc_ch].paritytype = pbuf[5]; + Line_Coding[cdc_ch].datatype = pbuf[6]; + + //Change_UART_Setting(cdc_ch); + break; + + case CDC_GET_LINE_CODING: + pbuf[0] = (uint8_t)(Line_Coding[cdc_ch].bitrate); + pbuf[1] = (uint8_t)(Line_Coding[cdc_ch].bitrate >> 8); + pbuf[2] = (uint8_t)(Line_Coding[cdc_ch].bitrate >> 16); + pbuf[3] = (uint8_t)(Line_Coding[cdc_ch].bitrate >> 24); + pbuf[4] = Line_Coding[cdc_ch].format; + pbuf[5] = Line_Coding[cdc_ch].paritytype; + pbuf[6] = Line_Coding[cdc_ch].datatype; + break; + + case CDC_SET_CONTROL_LINE_STATE: + + break; + + case CDC_SEND_BREAK: + + break; + + default: + break; + } + + return (USBD_OK); + /* USER CODE END 5 */ +} + +/** + * @brief Data received over USB OUT endpoint are sent over CDC interface + * through this function. + * + * @note + * This function will issue a NAK packet on any OUT packet received on + * USB endpoint until exiting this function. If you exit this function + * before transfer is complete on CDC interface (ie. using DMA controller) + * it will result in receiving more data while previous ones are still + * not sent. + * + * @param Buf: Buffer of data to be received + * @param Len: Number of data received (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_Receive(uint8_t cdc_ch, uint8_t *Buf, uint32_t *Len) +{ + /* USER CODE BEGIN 6 */ + //HAL_UART_Transmit_DMA(CDC_CH_To_UART_Handle(cdc_ch), Buf, *Len); + CDC_Transmit(cdc_ch, Buf, *Len); // echo back on same channel + + USBD_CDC_SetRxBuffer(cdc_ch, &hUsbDevice, &Buf[0]); + USBD_CDC_ReceivePacket(cdc_ch, &hUsbDevice); + return (USBD_OK); + /* USER CODE END 6 */ +} + +/** + * @brief CDC_TransmitCplt_FS + * Data transmited callback + * + * @note + * This function is IN transfer complete callback used to inform user that + * the submitted Data is successfully sent over USB. + * + * @param Buf: Buffer of data to be received + * @param Len: Number of data received (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_TransmitCplt(uint8_t cdc_ch, uint8_t *Buf, uint32_t *Len, uint8_t epnum) +{ + return (USBD_OK); +} + +/** + * @brief CDC_Transmit + * Data to send over USB IN endpoint are sent over CDC interface + * through this function. + * @note + * + * + * @param Buf: Buffer of data to be sent + * @param Len: Number of data to be sent (in bytes) + * @retval USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY + */ +uint8_t CDC_Transmit(uint8_t ch, uint8_t *Buf, uint16_t Len) +{ + uint8_t result = USBD_OK; + /* USER CODE BEGIN 7 */ + extern USBD_CDC_ACM_HandleTypeDef CDC_ACM_Class_Data[]; + USBD_CDC_ACM_HandleTypeDef *hcdc = NULL; + hcdc = &CDC_ACM_Class_Data[ch]; + if (hcdc->TxState != 0) + { + return USBD_BUSY; + } + USBD_CDC_SetTxBuffer(ch, &hUsbDevice, Buf, Len); + result = USBD_CDC_TransmitPacket(ch, &hUsbDevice); + /* USER CODE END 7 */ + return result; +} + +/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */ +//void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) +//{ +// /* Initiate next USB packet transfer once UART completes transfer (transmitting data over Tx line) */ +// //USBD_CDC_ReceivePacket(UART_Handle_TO_CDC_CH(huart), &hUsbDevice); +//} + +//void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) +//{ +// for (uint8_t i = 0; i < NUMBER_OF_CDC; i++) +// { +// uint32_t buffptr; +// uint32_t buffsize; +// +// if (Read_Index[i] != Write_Index[i]) +// { +// if (Read_Index[i] > Write_Index[i]) /* Rollback */ +// { +// buffsize = APP_TX_DATA_SIZE - Read_Index[i]; +// } +// else +// { +// buffsize = Write_Index[i] - Read_Index[i]; +// } +// +// buffptr = Read_Index[i]; +// +// USBD_CDC_SetTxBuffer(i, &hUsbDevice, &TX_Buffer[i][buffptr], buffsize); +// +// if (USBD_CDC_TransmitPacket(i, &hUsbDevice) == USBD_OK) +// { +// Read_Index[i] += buffsize; +// if (Read_Index[i] == APP_RX_DATA_SIZE) +// { +// Read_Index[i] = 0; +// } +// } +// } +// } +//} + +//void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) +//{ +// uint8_t cdc_ch = UART_Handle_TO_CDC_CH(huart); +// /* Increment Index for buffer writing */ +// Write_Index[cdc_ch]++; +// +// /* To avoid buffer overflow */ +// if (Write_Index[cdc_ch] == APP_RX_DATA_SIZE) +// { +// Write_Index[cdc_ch] = 0; +// } +// +// /* Start another reception: provide the buffer pointer with offset and the buffer size */ +// HAL_UART_Receive_IT(huart, (TX_Buffer[cdc_ch] + Write_Index[cdc_ch]), 1); +//} +/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_cdc_acm_if.h b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_cdc_acm_if.h new file mode 100644 index 0000000..0558650 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_cdc_acm_if.h @@ -0,0 +1,130 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : usbd_cdc_acm_if.h + * @version : v2.0_Cube + * @brief : Header for usbd_cdc_if.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_CDC_ACM_IF_H__ +#define __USBD_CDC_ACM_IF_H__ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_cdc_acm.h" + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @brief For Usb device. + * @{ + */ + +/** @defgroup USBD_CDC_IF USBD_CDC_IF + * @brief Usb VCP device module + * @{ + */ + +/** @defgroup USBD_CDC_IF_Exported_Defines USBD_CDC_IF_Exported_Defines + * @brief Defines. + * @{ + */ +/* USER CODE BEGIN EXPORTED_DEFINES */ + +/* USER CODE END EXPORTED_DEFINES */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Exported_Types USBD_CDC_IF_Exported_Types + * @brief Types. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_TYPES */ + +/* USER CODE END EXPORTED_TYPES */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Exported_Macros USBD_CDC_IF_Exported_Macros + * @brief Aliases. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_MACRO */ + +/* USER CODE END EXPORTED_MACRO */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Exported_Variables USBD_CDC_IF_Exported_Variables + * @brief Public variables. + * @{ + */ + +/** CDC Interface callback. */ +extern USBD_CDC_ACM_ItfTypeDef USBD_CDC_ACM_fops; + +/* USER CODE BEGIN EXPORTED_VARIABLES */ + +/* USER CODE END EXPORTED_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Exported_FunctionsPrototype USBD_CDC_IF_Exported_FunctionsPrototype + * @brief Public functions declaration. + * @{ + */ + +uint8_t CDC_Transmit(uint8_t ch, uint8_t* Buf, uint16_t Len); + +/* USER CODE BEGIN EXPORTED_FUNCTIONS */ + +/* USER CODE END EXPORTED_FUNCTIONS */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_CDC_ACM_IF_TEMPLATE_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_cdc_ecm_if.c b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_cdc_ecm_if.c new file mode 100644 index 0000000..c0db019 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_cdc_ecm_if.c @@ -0,0 +1,245 @@ +/** + ****************************************************************************** + * @file Src/usbd_cdc_ecm_if_template.c + * @author MCD Application Team + * @brief Source file for USBD CDC_ECM interface + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ + +#include "usbd_cdc_ecm_if.h" + +extern USBD_HandleTypeDef hUsbDevice; + +/* + Include here LwIP files if used +*/ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ +#pragma data_alignment=4 +#endif +__ALIGN_BEGIN static uint8_t UserRxBuffer[CDC_ECM_ETH_MAX_SEGSZE + 100]__ALIGN_END; /* Received Data over USB are stored in this buffer */ + +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ +#pragma data_alignment=4 +#endif +__ALIGN_BEGIN static uint8_t UserTxBuffer[CDC_ECM_ETH_MAX_SEGSZE + 100]__ALIGN_END; /* Received Data over CDC_ECM (CDC_ECM interface) are stored in this buffer */ + +static uint8_t CDC_ECMInitialized = 0U; + +/* Private function prototypes -----------------------------------------------*/ +static int8_t CDC_ECM_Itf_Init(void); +static int8_t CDC_ECM_Itf_DeInit(void); +static int8_t CDC_ECM_Itf_Control(uint8_t cmd, uint8_t *pbuf, uint16_t length); +static int8_t CDC_ECM_Itf_Receive(uint8_t *pbuf, uint32_t *Len); +static int8_t CDC_ECM_Itf_TransmitCplt(uint8_t *pbuf, uint32_t *Len, uint8_t epnum); +static int8_t CDC_ECM_Itf_Process(USBD_HandleTypeDef *pdev); + +USBD_CDC_ECM_ItfTypeDef USBD_CDC_ECM_fops = +{ + CDC_ECM_Itf_Init, + CDC_ECM_Itf_DeInit, + CDC_ECM_Itf_Control, + CDC_ECM_Itf_Receive, + CDC_ECM_Itf_TransmitCplt, + CDC_ECM_Itf_Process, + (uint8_t *)CDC_ECM_MAC_STR_DESC, +}; + +/* Private functions ---------------------------------------------------------*/ + +/** + * @brief CDC_ECM_Itf_Init + * Initializes the CDC_ECM media low layer + * @param None + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_ECM_Itf_Init(void) +{ + if (CDC_ECMInitialized == 0U) + { + /* + Initialize the TCP/IP stack here + */ + + CDC_ECMInitialized = 1U; + } + + /* Set Application Buffers */ + (void)USBD_CDC_ECM_SetTxBuffer(&hUsbDevice, UserTxBuffer, 0U); + (void)USBD_CDC_ECM_SetRxBuffer(&hUsbDevice, UserRxBuffer); + + return (0); +} + +/** + * @brief CDC_ECM_Itf_DeInit + * DeInitializes the CDC_ECM media low layer + * @param None + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_ECM_Itf_DeInit(void) +{ + USBD_CDC_ECM_HandleTypeDef *hcdc_cdc_ecm = (USBD_CDC_ECM_HandleTypeDef *)(hUsbDevice.pClassData_CDC_ECM); + + /* Notify application layer that link is down */ + hcdc_cdc_ecm->LinkStatus = 0U; + + return (0); +} + +/** + * @brief CDC_ECM_Itf_Control + * Manage the CDC_ECM class requests + * @param Cmd: Command code + * @param Buf: Buffer containing command data (request parameters) + * @param Len: Number of data to be sent (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_ECM_Itf_Control(uint8_t cmd, uint8_t *pbuf, uint16_t length) +{ + USBD_CDC_ECM_HandleTypeDef *hcdc_cdc_ecm = (USBD_CDC_ECM_HandleTypeDef *)(hUsbDevice.pClassData_CDC_ECM); + + switch (cmd) + { + case CDC_ECM_SEND_ENCAPSULATED_COMMAND: + /* Add your code here */ + break; + + case CDC_ECM_GET_ENCAPSULATED_RESPONSE: + /* Add your code here */ + break; + + case CDC_ECM_SET_ETH_MULTICAST_FILTERS: + /* Add your code here */ + break; + + case CDC_ECM_SET_ETH_PWRM_PATTERN_FILTER: + /* Add your code here */ + break; + + case CDC_ECM_GET_ETH_PWRM_PATTERN_FILTER: + /* Add your code here */ + break; + + case CDC_ECM_SET_ETH_PACKET_FILTER: + /* Check if this is the first time we enter */ + if (hcdc_cdc_ecm->LinkStatus == 0U) + { + /* + Setup the Link up at TCP/IP level + */ + hcdc_cdc_ecm->LinkStatus = 1U; + + /* Modification for MacOS which doesn't send SetInterface before receiving INs */ + if (hcdc_cdc_ecm->NotificationStatus == 0U) + { + /* Send notification: NETWORK_CONNECTION Event */ + (void)USBD_CDC_ECM_SendNotification(&hUsbDevice, ECM_NETWORK_CONNECTION, + CDC_ECM_NET_CONNECTED, NULL); + + /* Prepare for sending Connection Speed Change notification */ + hcdc_cdc_ecm->NotificationStatus = 1U; + } + } + /* Add your code here */ + break; + + case CDC_ECM_GET_ETH_STATISTIC: + /* Add your code here */ + break; + + default: + break; + } + UNUSED(length); + UNUSED(pbuf); + + return (0); +} + +/** + * @brief CDC_ECM_Itf_Receive + * Data received over USB OUT endpoint are sent over CDC_ECM interface + * through this function. + * @param Buf: Buffer of data to be transmitted + * @param Len: Number of data received (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_ECM_Itf_Receive(uint8_t *Buf, uint32_t *Len) +{ + /* Get the CDC_ECM handler pointer */ + USBD_CDC_ECM_HandleTypeDef *hcdc_cdc_ecm = (USBD_CDC_ECM_HandleTypeDef *)(hUsbDevice.pClassData_CDC_ECM); + + /* Call Eth buffer processing */ + hcdc_cdc_ecm->RxState = 1U; + + UNUSED(Len); + UNUSED(Buf); + + return (0); +} + +/** + * @brief CDC_ECM_Itf_TransmitCplt + * Data transmitted callback + * + * @note + * This function is IN transfer complete callback used to inform user that + * the submitted Data is successfully sent over USB. + * + * @param Buf: Buffer of data to be received + * @param Len: Number of data received (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_ECM_Itf_TransmitCplt(uint8_t *Buf, uint32_t *Len, uint8_t epnum) +{ + UNUSED(Buf); + UNUSED(Len); + UNUSED(epnum); + + return (0); +} + +/** + * @brief CDC_ECM_Itf_Process + * Data received over USB OUT endpoint are sent over CDC_ECM interface + * through this function. + * @param pdef: pointer to the USB Device Handle + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_ECM_Itf_Process(USBD_HandleTypeDef *pdev) +{ + /* Get the CDC_ECM handler pointer */ + USBD_CDC_ECM_HandleTypeDef *hcdc_cdc_ecm = (USBD_CDC_ECM_HandleTypeDef *)(pdev->pClassData_CDC_ECM); + + if ((hcdc_cdc_ecm != NULL) && (hcdc_cdc_ecm->LinkStatus != 0U)) + { + /* + Read a received packet from the Ethernet buffers and send it + to the lwIP for handling + Call here the TCP/IP background tasks. + */ + } + + return (0); +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_cdc_ecm_if.h b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_cdc_ecm_if.h new file mode 100644 index 0000000..7ce8714 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_cdc_ecm_if.h @@ -0,0 +1,82 @@ +/** + ****************************************************************************** + * @file Inc/usbd_cdc_ecm_if_template.h + * @author MCD Application Team + * @brief Header for usbd_cdc_ecm_if_template.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_CDC_ECM_IF_H +#define __USBD_CDC_ECM_IF_H + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_cdc_ecm.h" + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* Ensure this MAC address value is same as MAC_ADDRx declared in STM32xxx_conf.h */ +#define CDC_ECM_MAC_STR_DESC (uint8_t *)"000202030000" +#define CDC_ECM_MAC_ADDR0 0x00U /* 01 */ +#define CDC_ECM_MAC_ADDR1 0x02U /* 02 */ +#define CDC_ECM_MAC_ADDR2 0x02U /* 03 */ +#define CDC_ECM_MAC_ADDR3 0x03U /* 00 */ +#define CDC_ECM_MAC_ADDR4 0x00U /* 00 */ +#define CDC_ECM_MAC_ADDR5 0x00U /* 00 */ + +/* Max Number of Trials waiting for Tx ready */ +#define CDC_ECM_MAX_TX_WAIT_TRIALS 1000000U + +#define CDC_ECM_ETH_STATS_BYTE0 0U +/*(uint8_t)(CDC_ECM_XMIT_OK_VAL | CDC_ECM_RVC_OK_VAL | CDC_ECM_XMIT_ERROR_VAL | \ + CDC_ECM_RCV_ERROR_VAL | CDC_ECM_RCV_NO_BUFFER_VAL | CDC_ECM_DIRECTED_BYTES_XMIT_VAL | \ + CDC_ECM_DIRECTED_FRAMES_XMIT_VAL | CDC_ECM_MULTICAST_BYTES_XMIT_VAL) */ + +#define CDC_ECM_ETH_STATS_BYTE1 0U +/*(uint8_t)(CDC_ECM_MULTICAST_FRAMES_XMIT_VAL | CDC_ECM_BROADCAST_BYTES_XMIT_VAL | \ + CDC_ECM_BROADCAST_FRAMES_XMIT_VAL | CDC_ECM_DIRECTED_BYTES_RCV_VAL | \ + CDC_ECM_DIRECTED_FRAMES_RCV_VAL | CDC_ECM_MULTICAST_BYTES_RCV_VAL | \ + CDC_ECM_MULTICAST_FRAMES_RCV_VAL | CDC_ECM_BROADCAST_BYTES_RCV_VAL) */ + +#define CDC_ECM_ETH_STATS_BYTE2 0U +/*(uint8_t)(CDC_ECM_BROADCAST_FRAMES_RCV_VAL | CDC_ECM_RCV_CRC_ERROR_VAL | \ + CDC_ECM_TRANSMIT_QUEUE_LENGTH_VAL | CDC_ECM_RCV_ERROR_ALIGNMENT_VAL | \ + CDC_ECM_XMIT_ONE_COLLISION_VAL | CDC_ECM_XMIT_MORE_COLLISIONS_VAL | \ + CDC_ECM_XMIT_DEFERRED_VAL | CDC_ECM_XMIT_MAX_COLLISIONS_VAL) */ + +#define CDC_ECM_ETH_STATS_BYTE3 0U +/*(uint8_t)(CDC_ECM_RCV_OVERRUN_VAL | CDC_ECM_XMIT_UNDERRUN_VAL | CDC_ECM_XMIT_HEARTBEAT_FAILURE_VAL | \ + CDC_ECM_XMIT_TIMES_CRS_LOST_VAL | CDC_ECM_XMIT_LATE_COLLISIONS_VAL | CDC_ECM_ETH_STATS_RESERVED) */ + +/* Ethernet Maximum Segment size, typically 1514 bytes */ +#define CDC_ECM_ETH_MAX_SEGSZE 1514U + +/* Number of Ethernet multicast filters */ +#define CDC_ECM_ETH_NBR_MACFILTERS 0U + +/* Number of wakeup power filters */ +#define CDC_ECM_ETH_NBR_PWRFILTERS 0U + + +#define CDC_ECM_CONNECT_SPEED_UPSTREAM 0x004C4B40U /* 5Mbps */ +#define CDC_ECM_CONNECT_SPEED_DOWNSTREAM 0x004C4B40U /* 5Mbps */ + +extern USBD_CDC_ECM_ItfTypeDef USBD_CDC_ECM_fops; + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +#endif /* __USBD_CDC_ECM_IF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_cdc_rndis_if.c b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_cdc_rndis_if.c new file mode 100644 index 0000000..9a36f40 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_cdc_rndis_if.c @@ -0,0 +1,231 @@ +/** + ****************************************************************************** + * @file usbd_cdc_rndis_if_template.c + * @author MCD Application Team + * @brief Source file for USBD CDC_RNDIS interface template + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ + +/* Include TCP/IP stack header files */ +/* +#include "lwip/opt.h" +#include "lwip/init.h" +#include "lwip/dhcp.h" +#include "lwip/netif.h" +#include "lwip/timeouts.h" +#include "netif/etharp.h" +#include "http_cgi_ssi.h" +#include "ethernetif.h" +*/ + +#include "usbd_cdc_rndis_if.h" + +extern USBD_HandleTypeDef hUsbDevice; + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ +#pragma data_alignment=4 +#endif +__ALIGN_BEGIN uint8_t UserRxBuffer[CDC_RNDIS_ETH_MAX_SEGSZE + 100] __ALIGN_END; /* Received Data over USB are stored in this buffer */ + +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ +#pragma data_alignment=4 +#endif +__ALIGN_BEGIN static uint8_t UserTxBuffer[CDC_RNDIS_ETH_MAX_SEGSZE + 100] __ALIGN_END; /* Received Data over CDC_RNDIS (CDC_RNDIS interface) are stored in this buffer */ + +static uint8_t CDC_RNDISInitialized = 0U; + +/* Private function prototypes -----------------------------------------------*/ +static int8_t CDC_RNDIS_Itf_Init(void); +static int8_t CDC_RNDIS_Itf_DeInit(void); +static int8_t CDC_RNDIS_Itf_Control(uint8_t cmd, uint8_t *pbuf, uint16_t length); +static int8_t CDC_RNDIS_Itf_Receive(uint8_t *pbuf, uint32_t *Len); +static int8_t CDC_RNDIS_Itf_TransmitCplt(uint8_t *pbuf, uint32_t *Len, uint8_t epnum); +static int8_t CDC_RNDIS_Itf_Process(USBD_HandleTypeDef *pdev); + +USBD_CDC_RNDIS_ItfTypeDef USBD_CDC_RNDIS_fops = +{ + CDC_RNDIS_Itf_Init, + CDC_RNDIS_Itf_DeInit, + CDC_RNDIS_Itf_Control, + CDC_RNDIS_Itf_Receive, + CDC_RNDIS_Itf_TransmitCplt, + CDC_RNDIS_Itf_Process, + (uint8_t *)CDC_RNDIS_MAC_STR_DESC, +}; + +/* Private functions ---------------------------------------------------------*/ + +/** + * @brief CDC_RNDIS_Itf_Init + * Initializes the CDC_RNDIS media low layer + * @param None + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_RNDIS_Itf_Init(void) +{ + if (CDC_RNDISInitialized == 0U) + { + /* + Initialize the LwIP stack + Add your code here + + */ + + CDC_RNDISInitialized = 1U; + } + + /* Set Application Buffers */ + (void)USBD_CDC_RNDIS_SetTxBuffer(&hUsbDevice, UserTxBuffer, 0U); + (void)USBD_CDC_RNDIS_SetRxBuffer(&hUsbDevice, UserRxBuffer); + + return (0); +} + +/** + * @brief CDC_RNDIS_Itf_DeInit + * DeInitializes the CDC_RNDIS media low layer + * @param None + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_RNDIS_Itf_DeInit(void) +{ + USBD_CDC_RNDIS_HandleTypeDef *hcdc_cdc_rndis = (USBD_CDC_RNDIS_HandleTypeDef *)(hUsbDevice.pClassData_CDC_RNDIS); + + /* + Add your code here + */ + + /* Notify application layer that link is down */ + hcdc_cdc_rndis->LinkStatus = 0U; + + return (0); +} + +/** + * @brief CDC_RNDIS_Itf_Control + * Manage the CDC_RNDIS class requests + * @param Cmd: Command code + * @param Buf: Buffer containing command data (request parameters) + * @param Len: Number of data to be sent (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_RNDIS_Itf_Control(uint8_t cmd, uint8_t *pbuf, uint16_t length) +{ + USBD_CDC_RNDIS_HandleTypeDef *hcdc_cdc_rndis = (USBD_CDC_RNDIS_HandleTypeDef *)(hUsbDevice.pClassData_CDC_RNDIS); + + switch (cmd) + { + case CDC_RNDIS_SEND_ENCAPSULATED_COMMAND: + /* Add your code here */ + break; + + case CDC_RNDIS_GET_ENCAPSULATED_RESPONSE: + /* Check if this is the first time we enter */ + if (hcdc_cdc_rndis->LinkStatus == 0U) + { + /* Setup the Link up at TCP/IP stack level */ + hcdc_cdc_rndis->LinkStatus = 1U; + /* + Add your code here + */ + } + /* Add your code here */ + break; + + default: + /* Add your code here */ + break; + } + + UNUSED(length); + UNUSED(pbuf); + + return (0); +} + +/** + * @brief CDC_RNDIS_Itf_Receive + * Data received over USB OUT endpoint are sent over CDC_RNDIS interface + * through this function. + * @param Buf: Buffer of data to be transmitted + * @param Len: Number of data received (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_RNDIS_Itf_Receive(uint8_t *Buf, uint32_t *Len) +{ + /* Get the CDC_RNDIS handler pointer */ + USBD_CDC_RNDIS_HandleTypeDef *hcdc_cdc_rndis = (USBD_CDC_RNDIS_HandleTypeDef *)(hUsbDevice.pClassData_CDC_RNDIS); + + /* Call Eth buffer processing */ + hcdc_cdc_rndis->RxState = 1U; + + UNUSED(Buf); + UNUSED(Len); + + return (0); +} + +/** + * @brief CDC_RNDIS_Itf_TransmitCplt + * Data transmitted callback + * + * @note + * This function is IN transfer complete callback used to inform user that + * the submitted Data is successfully sent over USB. + * + * @param Buf: Buffer of data to be received + * @param Len: Number of data received (in bytes) + * @param epnum: EP number + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_RNDIS_Itf_TransmitCplt(uint8_t *Buf, uint32_t *Len, uint8_t epnum) +{ + UNUSED(Buf); + UNUSED(Len); + UNUSED(epnum); + + return (0); +} + +/** + * @brief CDC_RNDIS_Itf_Process + * Data received over USB OUT endpoint are sent over CDC_RNDIS interface + * through this function. + * @param pdef: pointer to the USB Device Handle + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_RNDIS_Itf_Process(USBD_HandleTypeDef *pdev) +{ + /* Get the CDC_RNDIS handler pointer */ + USBD_CDC_RNDIS_HandleTypeDef *hcdc_cdc_rndis = (USBD_CDC_RNDIS_HandleTypeDef *)(pdev->pClassData_CDC_RNDIS); + + if ((hcdc_cdc_rndis != NULL) && (hcdc_cdc_rndis->LinkStatus != 0U)) + { + /* + Add your code here + Read a received packet from the Ethernet buffers and send it + to the lwIP for handling + */ + } + + return (0); +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_cdc_rndis_if.h b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_cdc_rndis_if.h new file mode 100644 index 0000000..3cf0271 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_cdc_rndis_if.h @@ -0,0 +1,60 @@ +/** + ****************************************************************************** + * @file usbd_cdc_rndis_if_template.h + * @author MCD Application Team + * @brief Header for usbd_cdc_rndis_if.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_CDC_RNDIS_IF_H +#define __USBD_CDC_RNDIS_IF_H + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_cdc_rndis.h" + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* Ensure this MAC address value is same as MAC_ADDRx declared in STM32xxx_conf.h */ +#define CDC_RNDIS_MAC_STR_DESC (uint8_t *)"000202030000" +#define CDC_RNDIS_MAC_ADDR0 0x00U /* 01 */ +#define CDC_RNDIS_MAC_ADDR1 0x02U /* 02 */ +#define CDC_RNDIS_MAC_ADDR2 0x02U /* 03 */ +#define CDC_RNDIS_MAC_ADDR3 0x03U /* 00 */ +#define CDC_RNDIS_MAC_ADDR4 0x00U /* 00 */ +#define CDC_RNDIS_MAC_ADDR5 0x00U /* 00 */ + +#define USBD_CDC_RNDIS_VENDOR_DESC "STMicroelectronics" +#define USBD_CDC_RNDIS_LINK_SPEED 100000U /* 10Mbps */ +#define USBD_CDC_RNDIS_VID 0x0483U + +/* Max Number of Trials waiting for Tx ready */ +#define CDC_RNDIS_MAX_TX_WAIT_TRIALS 1000000U + +/* Ethernet Maximum Segment size, typically 1514 bytes */ +#define CDC_RNDIS_ETH_MAX_SEGSZE 1514U + +#define CDC_RNDIS_CONNECT_SPEED_UPSTREAM 0x1E000000U +#define CDC_RNDIS_CONNECT_SPEED_DOWNSTREAM 0x1E000000U + + +extern USBD_CDC_RNDIS_ItfTypeDef USBD_CDC_RNDIS_fops; + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ + +#endif /* __USBD_CDC_RNDIS_IF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_dfu_if.c b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_dfu_if.c new file mode 100644 index 0000000..6d85cff --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_dfu_if.c @@ -0,0 +1,253 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : usbd_dfu_if.c + * @brief : Usb device for Download Firmware Update. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_dfu_if.h" + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE END PV */ + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @brief Usb device. + * @{ + */ + +/** @defgroup USBD_DFU + * @brief Usb DFU device module. + * @{ + */ + +/** @defgroup USBD_DFU_Private_TypesDefinitions + * @brief Private types. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_TYPES */ + +/* USER CODE END PRIVATE_TYPES */ + +/** + * @} + */ + +/** @defgroup USBD_DFU_Private_Defines + * @brief Private defines. + * @{ + */ + +#define FLASH_DESC_STR "@Internal Flash /0x08000000/03*016Ka,01*016Kg,01*064Kg,07*128Kg,04*016Kg,01*064Kg,07*128Kg" + +/* USER CODE BEGIN PRIVATE_DEFINES */ + +/* USER CODE END PRIVATE_DEFINES */ + +/** + * @} + */ + +/** @defgroup USBD_DFU_Private_Macros + * @brief Private macros. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_MACRO */ + +/* USER CODE END PRIVATE_MACRO */ + +/** + * @} + */ + +/** @defgroup USBD_DFU_Private_Variables + * @brief Private variables. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_VARIABLES */ + +/* USER CODE END PRIVATE_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_DFU_Exported_Variables + * @brief Public variables. + * @{ + */ + +extern USBD_HandleTypeDef hUsbDevice; + +/* USER CODE BEGIN EXPORTED_VARIABLES */ + +/* USER CODE END EXPORTED_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_DFU_Private_FunctionPrototypes + * @brief Private functions declaration. + * @{ + */ + +static uint16_t MEM_If_Init(void); +static uint16_t MEM_If_Erase(uint32_t Add); +static uint16_t MEM_If_Write(uint8_t *src, uint8_t *dest, uint32_t Len); +static uint8_t *MEM_If_Read(uint8_t *src, uint8_t *dest, uint32_t Len); +static uint16_t MEM_If_DeInit(void); +static uint16_t MEM_If_GetStatus(uint32_t Add, uint8_t Cmd, uint8_t *buffer); + +/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */ + +/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */ + +/** + * @} + */ + +#if defined ( __ICCARM__ ) /* IAR Compiler */ + #pragma data_alignment=4 +#endif + +__ALIGN_BEGIN USBD_DFU_MediaTypeDef USBD_DFU_fops __ALIGN_END = +{ + (uint8_t*)FLASH_DESC_STR, + MEM_If_Init, + MEM_If_DeInit, + MEM_If_Erase, + MEM_If_Write, + MEM_If_Read, + MEM_If_GetStatus +}; + +/* Private functions ---------------------------------------------------------*/ + +/** + * @brief Memory initialization routine. + * @retval USBD_OK if operation is successful, MAL_FAIL else. + */ +uint16_t MEM_If_Init(void) +{ + /* USER CODE BEGIN 6 */ + return (USBD_OK); + /* USER CODE END 6 */ +} + +/** + * @brief De-Initializes Memory. + * @retval USBD_OK if operation is successful, MAL_FAIL else. + */ +uint16_t MEM_If_DeInit(void) +{ + /* USER CODE BEGIN 7 */ + return (USBD_OK); + /* USER CODE END 7 */ +} + +/** + * @brief Erase sector. + * @param Add: Address of sector to be erased. + * @retval USBD_OK if operation is successful, MAL_FAIL else. + */ +uint16_t MEM_If_Erase(uint32_t Add) +{ + /* USER CODE BEGIN 8 */ + return (USBD_OK); + /* USER CODE END 8 */ +} + +/** + * @brief Memory write routine. + * @param src: Pointer to the source buffer. Address to be written to. + * @param dest: Pointer to the destination buffer. + * @param Len: Number of data to be written (in bytes). + * @retval USBD_OK if operation is successful, MAL_FAIL else. + */ +uint16_t MEM_If_Write(uint8_t *src, uint8_t *dest, uint32_t Len) +{ + /* USER CODE BEGIN 9 */ + return (USBD_OK); + /* USER CODE END 9 */ +} + +/** + * @brief Memory read routine. + * @param src: Pointer to the source buffer. Address to be written to. + * @param dest: Pointer to the destination buffer. + * @param Len: Number of data to be read (in bytes). + * @retval Pointer to the physical address where data should be read. + */ +uint8_t *MEM_If_Read(uint8_t *src, uint8_t *dest, uint32_t Len) +{ + /* Return a valid address to avoid HardFault */ + /* USER CODE BEGIN 10 */ + return (uint8_t*)(USBD_OK); + /* USER CODE END 10 */ +} + +/** + * @brief Get status routine. + * @param Add: Address to be read from. + * @param Cmd: Number of data to be read (in bytes). + * @param buffer: used for returning the time necessary for a program or an erase operation + * @retval 0 if operation is successful + */ +uint16_t MEM_If_GetStatus(uint32_t Add, uint8_t Cmd, uint8_t *buffer) +{ + /* USER CODE BEGIN 11 */ + switch(Cmd) + { + case DFU_MEDIA_PROGRAM: + + break; + + case DFU_MEDIA_ERASE: + default: + + break; + } + return (USBD_OK); + /* USER CODE END 11 */ +} + +/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */ + +/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_dfu_if.h b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_dfu_if.h new file mode 100644 index 0000000..d21d214 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_dfu_if.h @@ -0,0 +1,128 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : usbd_dfu_if.h + * @brief : Header for usbd_dfu_if.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_DFU_IF_H__ +#define __USBD_DFU_IF_H__ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_dfu.h" + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @brief For Usb device. + * @{ + */ + +/** @defgroup USBD_MEDIA USBD_MEDIA + * @brief Header file for the usbd_dfu_if.c file. + * @{ + */ + +/** @defgroup USBD_MEDIA_Exported_Defines USBD_MEDIA_Exported_Defines + * @brief Defines. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_DEFINES */ + +/* USER CODE END EXPORTED_DEFINES */ + +/** + * @} + */ + +/** @defgroup USBD_MEDIA_Exported_Types USBD_MEDIA_Exported_Types + * @brief Types. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_TYPES */ + +/* USER CODE END EXPORTED_TYPES */ + +/** + * @} + */ + +/** @defgroup USBD_MEDIA_Exported_Macros USBD_MEDIA_Exported_Macros + * @brief Aliases. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_MACRO */ + +/* USER CODE END EXPORTED_MACRO */ + +/** + * @} + */ + +/** @defgroup USBD_MEDIA_Exported_Variables USBD_MEDIA_Exported_Variables + * @brief Public variables. + * @{ + */ + +/** MEDIA Interface callback. */ +extern USBD_DFU_MediaTypeDef USBD_DFU_fops; + +/* USER CODE BEGIN EXPORTED_VARIABLES */ + +/* USER CODE END EXPORTED_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_MEDIA_Exported_FunctionsPrototype USBD_MEDIA_Exported_FunctionsPrototype + * @brief Public functions declaration. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_FUNCTIONS */ + +/* USER CODE END EXPORTED_FUNCTIONS */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_DFU_IF_H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_hid_custom_if.c b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_hid_custom_if.c new file mode 100644 index 0000000..de07897 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_hid_custom_if.c @@ -0,0 +1,256 @@ +/** + ****************************************************************************** + * @file : usbd_custom_hid_if.c + * @version : v1.0_Cube + * @brief : USB Device Custom HID interface file. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions are met: + * + * 1. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_hid_custom_if.h" + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ +uint8_t buffer[0x40]; +/* USER CODE END PV */ + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @brief Usb device. + * @{ + */ + +/** @addtogroup USBD_CUSTOM_HID + * @{ + */ + +/** @defgroup USBD_CUSTOM_HID_Private_TypesDefinitions USBD_CUSTOM_HID_Private_TypesDefinitions + * @brief Private types. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_TYPES */ + +/* USER CODE END PRIVATE_TYPES */ + +/** + * @} + */ + +/** @defgroup USBD_CUSTOM_HID_Private_Defines USBD_CUSTOM_HID_Private_Defines + * @brief Private defines. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_DEFINES */ + +/* USER CODE END PRIVATE_DEFINES */ + +/** + * @} + */ + +/** @defgroup USBD_CUSTOM_HID_Private_Macros USBD_CUSTOM_HID_Private_Macros + * @brief Private macros. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_MACRO */ + +/* USER CODE END PRIVATE_MACRO */ + +/** + * @} + */ + +/** @defgroup USBD_CUSTOM_HID_Private_Variables USBD_CUSTOM_HID_Private_Variables + * @brief Private variables. + * @{ + */ + +/** Usb HID report descriptor. */ +__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END = + { + /* USER CODE BEGIN 0 */ + 0x06, 0x00, 0xff, //Usage Page(Undefined ) + 0x09, 0x01, // USAGE (Undefined) + 0xa1, 0x01, // COLLECTION (Application) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) + 0x75, 0x08, // REPORT_SIZE (8) + 0x95, 0x40, // REPORT_COUNT (64) + 0x09, 0x01, // USAGE (Undefined) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x95, 0x40, // REPORT_COUNT (64) + 0x09, 0x01, // USAGE (Undefined) + 0x91, 0x02, // OUTPUT (Data,Var,Abs) + 0x95, 0x01, // REPORT_COUNT (1) + 0x09, 0x01, // USAGE (Undefined) + 0xb1, 0x02, // FEATURE (Data,Var,Abs) + + /* USER CODE END 0 */ + 0xC0 /* END_COLLECTION */ +}; + +/* USER CODE BEGIN PRIVATE_VARIABLES */ + +/* USER CODE END PRIVATE_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_CUSTOM_HID_Exported_Variables USBD_CUSTOM_HID_Exported_Variables + * @brief Public variables. + * @{ + */ +extern USBD_HandleTypeDef hUsbDevice; + +/* USER CODE BEGIN EXPORTED_VARIABLES */ + +/* USER CODE END EXPORTED_VARIABLES */ +/** + * @} + */ + +/** @defgroup USBD_CUSTOM_HID_Private_FunctionPrototypes USBD_CUSTOM_HID_Private_FunctionPrototypes + * @brief Private functions declaration. + * @{ + */ + +static int8_t CUSTOM_HID_Init(void); +static int8_t CUSTOM_HID_DeInit(void); +static int8_t CUSTOM_HID_OutEvent(uint8_t event_idx, uint8_t state); + +/** + * @} + */ + +USBD_CUSTOM_HID_ItfTypeDef USBD_CustomHID_fops = {CUSTOM_HID_ReportDesc, + CUSTOM_HID_Init, + CUSTOM_HID_DeInit, + CUSTOM_HID_OutEvent}; + +/** @defgroup USBD_CUSTOM_HID_Private_Functions USBD_CUSTOM_HID_Private_Functions + * @brief Private functions. + * @{ + */ + +/* Private functions ---------------------------------------------------------*/ + +/** + * @brief Initializes the CUSTOM HID media low layer + * @retval USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CUSTOM_HID_Init(void) +{ + /* USER CODE BEGIN 4 */ + return (USBD_OK); + /* USER CODE END 4 */ +} + +/** + * @brief DeInitializes the CUSTOM HID media low layer + * @retval USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CUSTOM_HID_DeInit(void) +{ + /* USER CODE BEGIN 5 */ + return (USBD_OK); + /* USER CODE END 5 */ +} + +/** + * @brief Manage the CUSTOM HID class events + * @param event_idx: Event index + * @param state: Event state + * @retval USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CUSTOM_HID_OutEvent(uint8_t event_idx, uint8_t state) +{ + /* USER CODE BEGIN 6 */ + //memcpy(buffer, state, 0x40); + //USBD_CUSTOM_HID_SendReport(&hUsbDevice, (uint8_t *)buffer, 0x40); + return (USBD_OK); + /* USER CODE END 6 */ +} + +/* USER CODE BEGIN 7 */ +/** + * @brief Send the report to the Host + * @param report: The report to be sent + * @param len: The report length + * @retval USBD_OK if all operations are OK else USBD_FAIL + */ +/* +static int8_t USBD_CUSTOM_HID_SendReport(uint8_t *report, uint16_t len) +{ + return USBD_CUSTOM_HID_SendReport(&hUsbDevice, report, len); +} +*/ +/* USER CODE END 7 */ + +/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */ + +/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_hid_custom_if.h b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_hid_custom_if.h new file mode 100644 index 0000000..ee297a1 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_hid_custom_if.h @@ -0,0 +1,157 @@ +/** + ****************************************************************************** + * @file : usbd_custom_hid_if.h + * @version : v1.0_Cube + * @brief : Header for usbd_custom_hid_if.c file. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions are met: + * + * 1. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_CUSTOM_HID_IF_H__ +#define __USBD_CUSTOM_HID_IF_H__ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_hid_custom.h" + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @brief For Usb device. + * @{ + */ + +/** @defgroup USBD_CUSTOM_HID USBD_CUSTOM_HID + * @brief Usb custom human interface device module. + * @{ + */ + +/** @defgroup USBD_CUSTOM_HID_Exported_Defines USBD_CUSTOM_HID_Exported_Defines + * @brief Defines. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_DEFINES */ + +/* USER CODE END EXPORTED_DEFINES */ + +/** + * @} + */ + +/** @defgroup USBD_CUSTOM_HID_Exported_Types USBD_CUSTOM_HID_Exported_Types + * @brief Types. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_TYPES */ + +/* USER CODE END EXPORTED_TYPES */ + +/** + * @} + */ + +/** @defgroup USBD_CUSTOM_HID_Exported_Macros USBD_CUSTOM_HID_Exported_Macros + * @brief Aliases. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_MACRO */ + +/* USER CODE END EXPORTED_MACRO */ + +/** + * @} + */ + +/** @defgroup USBD_CUSTOM_HID_Exported_Variables USBD_CUSTOM_HID_Exported_Variables + * @brief Public variables. + * @{ + */ + +/** CUSTOMHID Interface callback. */ +extern USBD_CUSTOM_HID_ItfTypeDef USBD_CustomHID_fops; + +/* USER CODE BEGIN EXPORTED_VARIABLES */ + +/* USER CODE END EXPORTED_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_CUSTOM_HID_Exported_FunctionsPrototype USBD_CUSTOM_HID_Exported_FunctionsPrototype + * @brief Public functions declaration. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_FUNCTIONS */ + +/* USER CODE END EXPORTED_FUNCTIONS */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_CUSTOM_HID_IF_H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_msc_if.c b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_msc_if.c index 4b5f130..195cbec 100644 --- a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_msc_if.c +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_msc_if.c @@ -64,7 +64,7 @@ uint8_t MSC_Storage[32*1024]; */ #define STORAGE_LUN_NBR 1 -#define STORAGE_BLK_NBR 100*1024/512 +#define STORAGE_BLK_NBR 32*1024/512 #define STORAGE_BLK_SIZ 512 /* USER CODE BEGIN PRIVATE_DEFINES */ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_printer_if.c b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_printer_if.c new file mode 100644 index 0000000..3cde8c9 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_printer_if.c @@ -0,0 +1,210 @@ +/** + ****************************************************************************** + * @file usbd_printer_if_template.c + * @author MCD Application Team + * @brief Generic media access Layer. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * 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 + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_printer_if.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_PRNT + * @brief usbd core module + * @{ + */ + +/** @defgroup USBD_PRNT_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_PRNT_Private_Defines + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_PRNT_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_PRNT_Private_FunctionPrototypes + * @{ + */ + +static int8_t PRINTER_Init(void); +static int8_t PRINTER_DeInit(void); +static int8_t PRINTER_Control_req(uint8_t req, uint8_t *pbuf, uint16_t *length); +static int8_t PRINTER_Receive(uint8_t *pbuf, uint32_t *Len); + +/*printer Private function prototypes*/ +void PRINTER_PageEndManager(uint8_t *Buf, uint32_t Len); + +USBD_PRNT_ItfTypeDef USBD_PRNT_fops = {PRINTER_Init, + PRINTER_DeInit, + PRINTER_Control_req, + PRINTER_Receive}; + +static uint8_t PRNT_DEVICE_ID[] = + { + 0x00, 0x6D, + 'M', 'A', 'N', 'U', 'F', 'A', 'C', 'T', 'U', 'R', 'E', 'R', ':', + 'S', 'T', 'M', 'i', 'c', 'r', 'o', 'e', 'l', 'e', 'c', 't', 'r', 'o', 'n', 'i', 'c', 's', ';', + 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'D', 'L', ',', 'P', 'C', 'P', ';', + 'M', 'O', 'D', 'E', 'L', ':', + 'U', 'S', 'B', 'P', 'r', 'i', 'n', 't', 'e', 'r', ';', + 'C', 'O', 'M', 'M', 'E', 'N', 'T', ':', + 'G', 'o', 'o', 'd', ' ', '!', ';', + 'A', 'C', 'T', 'I', 'V', 'E', ' ', 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'P', ';'}; + +/* Private functions ---------------------------------------------------------*/ + +/** + * @brief PRINTER_Init + * Initializes the PRNT media low layer + * @param None + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t PRINTER_Init(void) +{ + /* + Add your initialization code here + */ + return (0); +} + +/** + * @brief PRINTER_DeInit + * DeInitializes the PRNT media low layer + * @param None + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t PRINTER_DeInit(void) +{ + /* + Add your deinitialization code here + */ + return (0); +} + +/** + * @brief PRINTER_Receive + * Data received over USB OUT endpoint are sent over PRNT interface + * through this function. + * + * @note + * This function will issue a NAK packet on any OUT packet received on + * USB endpoint untill exiting this function. If you exit this function + * before transfer is complete on PRNT interface (ie. using DMA controller) + * it will result in receiving more data while previous ones are still + * not sent. + * + * @param Buf: Buffer of data to be received + * @param Len: Number of data received (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t PRINTER_Receive(uint8_t *Buf, uint32_t *Len) +{ + UNUSED(Buf); + UNUSED(Len); + + return (0); +} + +/** + * @brief PRINTER_Itf_Control_req + * Manage the PRNT class requests + * @param req: Command code + * @param pbuf: Buffer containing command data (request parameters) + * @param length: Number of data to be sent (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t PRINTER_Control_req(uint8_t req, uint8_t *pbuf, uint16_t *length) +{ + uint32_t i = 0; + + /* Check on the setup request value */ + switch (req) + { + /* Get Printer Device ID request */ + case PRNT_GET_DEVICE_ID: + /* Not using for loop here due to MISRA-C2012-Rule-16.1 */ + while (i < sizeof(PRNT_DEVICE_ID)) + { + pbuf[i] = PRNT_DEVICE_ID[i]; + i++; + } + *length = i; + break; + + /* Get Printer current status */ + case PRNT_GET_PORT_STATUS: + pbuf[0] = PRNT_STATUS_PAPER_EMPTY | + PRNT_STATUS_SELECTED | + PRNT_STATUS_NO_ERROR; + + *length = 1U; + break; + + /* Printer SOFT RESET request: cleanup pending tasks */ + case PRNT_SOFT_RESET: + //(void)f_close(&hSD.MyFile); + break; + + default: + /* Unkown commands are not managed */ + break; + } + + return USBD_OK; +} + +/** +* @brief PRINTER_PageEndManager, defined by user +* Call this function frequently to check if data is received. +* @param Buf: Buffer of data to be received +* @param Len: Number of data received (in bytes) +*/ +void PRINTER_PageEndManager(uint8_t *Buf, uint32_t Len) +{ + UNUSED(Buf); + UNUSED(Len); +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_printer_if.h b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_printer_if.h new file mode 100644 index 0000000..a3e7f14 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_printer_if.h @@ -0,0 +1,45 @@ +/** + ****************************************************************************** + * @file usbd_printer_if_template.h + * @author MCD Application Team + * @brief Header for usbd_PRNT_if_template.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * 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 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_PRNT_IF_TEMPLATE_H +#define __USBD_PRNT_IF_TEMPLATE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_printer.h" + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +extern USBD_PRNT_ItfTypeDef USBD_PRNT_fops; + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_PRNT_IF_TEMPLATE_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_video_if.c b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_video_if.c new file mode 100644 index 0000000..cdf29e1 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_video_if.c @@ -0,0 +1,222 @@ +/** + ****************************************************************************** + * @file usbd_video_if_template.c + * @author MCD Application Team + * @brief Template file for Video Interface application layer functions + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_video_if.h" + +/* Include you image binary file here + Binary image template shall provide: + - tImagesList: table containing pointers to all images + - tImagesSizes: table containing sizes of each image respectively + - img_count: global image counter variable + - IMG_NBR: Total image number + + To generate such file, it is possible to use tools converting video to MJPEG then to JPEG images. + */ +/* #include "img_bin.h" */ + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE END PV */ + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @brief Usb device library. + * @{ + */ + +/** @addtogroup USBD_VIDEO_IF + * @{ + */ + +/** @defgroup USBD_VIDEO_IF_Private_TypesDefinitions + * @brief Private types. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_TYPES */ + +/* USER CODE END PRIVATE_TYPES */ + +/** + * @} + */ + +/** @defgroup USBD_VIDEO_IF_Private_Defines + * @brief Private defines. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_DEFINES */ + +/* USER CODE END PRIVATE_DEFINES */ + +/** + * @} + */ + +/** @defgroup USBD_VIDEO_IF_Private_Macros + * @brief Private macros. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_MACRO */ + +/* USER CODE END PRIVATE_MACRO */ + +/** + * @} + */ + +/** @defgroup USBD_VIDEO_IF_Private_Variables + * @brief Private variables. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_VARIABLES */ + +/* USER CODE END PRIVATE_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_VIDEO_IF_Exported_Variables + * @brief Public variables. + * @{ + */ + + + +/* USER CODE BEGIN EXPORTED_VARIABLES */ + +/* USER CODE END EXPORTED_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_VIDEO_IF_Private_FunctionPrototypes + * @brief Private functions declaration. + * @{ + */ + +static int8_t VIDEO_Itf_Init(void); +static int8_t VIDEO_Itf_DeInit(void); +static int8_t VIDEO_Itf_Control(uint8_t cmd, uint8_t *pbuf, uint16_t length); +static int8_t VIDEO_Itf_Data(uint8_t **pbuf, uint16_t *psize, uint16_t *pcktidx); + + +/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */ + +/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */ + +/** + * @} + */ + +USBD_VIDEO_ItfTypeDef USBD_VIDEO_fops_FS = +{ + VIDEO_Itf_Init, + VIDEO_Itf_DeInit, + VIDEO_Itf_Control, + VIDEO_Itf_Data, +}; + +/* Private functions ---------------------------------------------------------*/ +/** + * @brief Initializes the VIDEO media low layer over USB FS IP + * @param VIDEOFreq: VIDEO frequency used to play the VIDEO stream. + * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) + * @param options: Reserved for future use + * @retval USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t VIDEO_Itf_Init(void) +{ + /* + Add your initialization code here + */ + + return (0); +} + +/** + * @brief TEMPLATE_DeInit + * DeInitializes the UVC media low layer + * @param None + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t VIDEO_Itf_DeInit(void) +{ + /* + Add your deinitialization code here + */ + return (0); +} + + +/** + * @brief TEMPLATE_Control + * Manage the UVC class requests + * @param Cmd: Command code + * @param Buf: Buffer containing command data (request parameters) + * @param Len: Number of data to be sent (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t VIDEO_Itf_Control(uint8_t cmd, uint8_t *pbuf, uint16_t length) +{ + + return (0); +} + +/** + * @brief TEMPLATE_Data + * Manage the UVC data packets + * @param pbuf: pointer to the buffer data to be filled + * @param psize: pointer tot he current packet size to be filled + * @param pcktidx: pointer to the current packet index in the current image + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t VIDEO_Itf_Data(uint8_t **pbuf, uint16_t *psize, uint16_t *pcktidx) +{ + + return (0); +} + +/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */ + +/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_video_if.h b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_video_if.h new file mode 100644 index 0000000..036c7aa --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/App/usbd_video_if.h @@ -0,0 +1,142 @@ +/** + ****************************************************************************** + * @file usbd_video_if_template.h + * @author MCD Application Team + * @brief Template Header file for the video Interface application layer functions + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_VIDEO_IF_H__ +#define __USBD_VIDEO_IF_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_video.h" + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @brief For Usb device. + * @{ + */ + +/** @defgroup USBD_VIDEO_IF + * @brief Usb VIDEO interface device module. + * @{ + */ + +/** @defgroup USBD_VIDEO_IF_Exported_Defines + * @brief Defines. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_DEFINES */ + +/* USER CODE END EXPORTED_DEFINES */ + +/** + * @} + */ + +/** @defgroup USBD_VIDEO_IF_Exported_Types + * @brief Types. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_TYPES */ + +/* USER CODE END EXPORTED_TYPES */ + +/** + * @} + */ + +/** @defgroup USBD_VIDEO_IF_Exported_Macros + * @brief Aliases. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_MACRO */ + +/* USER CODE END EXPORTED_MACRO */ + +/** + * @} + */ + +/** @defgroup USBD_VIDEO_IF_Exported_Variables + * @brief Public variables. + * @{ + */ + +/** VIDEO_IF Interface callback. */ +extern USBD_VIDEO_ItfTypeDef USBD_VIDEO_fops_FS; + +/* USER CODE BEGIN EXPORTED_VARIABLES */ + +/* USER CODE END EXPORTED_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_VIDEO_IF_Exported_FunctionsPrototype + * @brief Public functions declaration. + * @{ + */ + +/** + * @brief Manages the DMA full transfer complete event. + * @retval None + */ +void TransferComplete_CallBack_FS(void); + +/** + * @brief Manages the DMA half transfer complete event. + * @retval None + */ +void HalfTransfer_CallBack_FS(void); + +/* USER CODE BEGIN EXPORTED_FUNCTIONS */ + +/* USER CODE END EXPORTED_FUNCTIONS */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* USBD_VIDEO_IF_H_ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + + diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/AUDIO_COMMON/usbd_audio.h b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/AUDIO_COMMON/usbd_audio.h new file mode 100644 index 0000000..3c79c6e --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/AUDIO_COMMON/usbd_audio.h @@ -0,0 +1,84 @@ +#ifndef _AUDIO_COMMON_USBD_AUDIO_H_ +#define _AUDIO_COMMON_USBD_AUDIO_H_ + +#include "usbd_ioreq.h" + +#define AUDIO_HS_BINTERVAL 0x01U + +#define AUDIO_FS_BINTERVAL 0x01U + + +#define AUDIO_INTERFACE_DESC_SIZE 0x09U +#define USB_AUDIO_DESC_SIZ 0x09U +#define AUDIO_STANDARD_ENDPOINT_DESC_SIZE 0x09U +#define AUDIO_STREAMING_ENDPOINT_DESC_SIZE 0x07U + +#define AUDIO_DESCRIPTOR_TYPE 0x21U +#define USB_DEVICE_CLASS_AUDIO 0x01U +#define AUDIO_SUBCLASS_AUDIOCONTROL 0x01U +#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02U +#define AUDIO_PROTOCOL_UNDEFINED 0x00U +#define AUDIO_STREAMING_GENERAL 0x01U +#define AUDIO_STREAMING_FORMAT_TYPE 0x02U + +/* Audio Descriptor Types */ +#define AUDIO_INTERFACE_DESCRIPTOR_TYPE 0x24U +#define AUDIO_ENDPOINT_DESCRIPTOR_TYPE 0x25U + +/* Audio Control Interface Descriptor Subtypes */ +#define AUDIO_CONTROL_HEADER 0x01U +#define AUDIO_CONTROL_INPUT_TERMINAL 0x02U +#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03U +#define AUDIO_CONTROL_FEATURE_UNIT 0x06U + +#define AUDIO_INPUT_TERMINAL_DESC_SIZE 0x0CU +#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE 0x09U +#define AUDIO_STREAMING_INTERFACE_DESC_SIZE 0x07U + +#define AUDIO_CONTROL_MUTE 0x0001U + +#define AUDIO_FORMAT_TYPE_I 0x01U +#define AUDIO_FORMAT_TYPE_III 0x03U + +#define AUDIO_ENDPOINT_GENERAL 0x01U + +#define AUDIO_REQ_GET_CUR 0x81U +#define AUDIO_REQ_GET_MIN 0x82 +#define AUDIO_REQ_GET_MAX 0x83 +#define AUDIO_REQ_GET_RES 0x84 +#define AUDIO_REQ_SET_CUR 0x01U + +#define AUDIO_STREAMING_CTRL 0x02U + + +/* Audio Commands enmueration */ +typedef enum +{ + AUDIO_CMD_START = 1, + AUDIO_CMD_PLAY, + AUDIO_CMD_STOP, +} AUDIO_CMD_TypeDef; + +typedef enum +{ + AUDIO_OFFSET_NONE = 0, + AUDIO_OFFSET_HALF, + AUDIO_OFFSET_FULL, + AUDIO_OFFSET_UNKNOWN, +} AUDIO_OffsetTypeDef; + +/** +* @} +*/ + +/** @defgroup USBD_AUDIO_IN_Exported_TypesDefinitions +* @{ +*/ +typedef struct +{ + uint8_t cmd; + uint8_t data[USB_MAX_EP0_SIZE]; + uint8_t len; + uint8_t unit; +} USBD_AUDIO_ControlTypeDef; +#endif /* _AUDIO_COMMON_USBD_AUDIO_H_ */ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/AUDIO_MIC/Inc/usbd_audio_mic.h b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/AUDIO_MIC/Inc/usbd_audio_mic.h new file mode 100644 index 0000000..1d2810f --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/AUDIO_MIC/Inc/usbd_audio_mic.h @@ -0,0 +1,166 @@ +/** +****************************************************************************** +* @file usbd_audio_in.h +* @author Central Labs +* @version V2.4.2 MOD +* @date 01-Sep-2016 + * @brief header file for the usbd_audio.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_AUDIO_MIC_H_ +#define __USBD_AUDIO_MIC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ioreq.h" +#include "usbd_audio.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_AUDIO + * @brief This file is the Header file for usbd_audio.c + * @{ + */ + + +/** @defgroup USBD_AUDIO_Exported_Defines + * @{ + */ + +#define AUDIO_MIC_STR_DESC "STM32 MICROPHONE" + +/* AUDIO Class Config */ +#define AUDIO_MIC_CHANNELS 0x01 +#define AUDIO_MIC_SMPL_FREQ 16000U +#define USBD_AUDIO_MIC_CONFIG_DESC_SIZE (116 + AUDIO_MIC_CHANNELS) + + + +#define AUDIO_MIC_VOL_MIN 0xDBE0 +#define AUDIO_MIC_VOL_RES 0x0023 +#define AUDIO_MIC_VOL_MAX 0x0000 +#define AUDIO_MIC_PACKET (uint32_t)((((AUDIO_MIC_SMPL_FREQ/1000)+2)*8)*2) +#define AUDIO_MIC_TERMINAL_ID 1 +#define AUDIO_MIC_FU_ID 2 +#define AUDIO_MIC_OUT_TERMINAL_ID 3 + +/* Buffering state definitions */ +typedef enum +{ + STATE_USB_WAITING_FOR_INIT = 0, + STATE_USB_IDLE = 1, + STATE_USB_REQUESTS_STARTED = 2, + STATE_USB_BUFFER_WRITE_STARTED = 3, +} AUDIO_MIC_StatesTypeDef; + +/* Number of sub-packets in the audio transfer buffer.*/ +#define AUDIO_MIC_PACKET_NUM 20 + +#define TIMEOUT_VALUE 200 + + +typedef struct +{ + __IO uint32_t alt_setting; + uint8_t channels; + uint32_t frequency; + __IO int16_t timeout; + uint16_t buffer_length; + uint16_t dataAmount; + uint16_t paketDimension; + uint8_t state; + uint16_t rd_ptr; + uint16_t wr_ptr; + uint8_t upper_treshold; + uint8_t lower_treshold; + USBD_AUDIO_ControlTypeDef control; + uint8_t *buffer; +} USBD_AUDIO_MIC_HandleTypeDef; + +typedef struct +{ + int8_t (*Init)(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr); + int8_t (*DeInit)(uint32_t options); + int8_t (*Record)(void); + int8_t (*VolumeCtl)(int16_t Volume); + int8_t (*MuteCtl)(uint8_t cmd); + int8_t (*Stop)(void); + int8_t (*Pause)(void); + int8_t (*Resume)(void); + int8_t (*CommandMgr)(uint8_t cmd); +} USBD_AUDIO_MIC_ItfTypeDef; +/** +* @} +*/ + +/** @defgroup USBD_AUDIO_IN_Exported_Macros +* @{ +*/ + +/** +* @} +*/ + +/** @defgroup USBD_AUDIO_IN_Exported_Variables +* @{ +*/ + +extern USBD_ClassTypeDef USBD_AUDIO_MIC; + +extern uint8_t AUDIO_MIC_EP; +extern uint8_t AUDIO_MIC_AC_ITF_NBR; +extern uint8_t AUDIO_MIC_AS_ITF_NBR; +extern uint8_t AUDIO_MIC_STR_DESC_IDX; + +/** +* @} +*/ + +/** @defgroup USBD_AUDIO_IN_Exported_Functions +* @{ +*/ +uint8_t USBD_AUDIO_MIC_RegisterInterface(USBD_HandleTypeDef *pdev, + USBD_AUDIO_MIC_ItfTypeDef *fops); +uint8_t USBD_AUDIO_MIC_Data_Transfer(USBD_HandleTypeDef *pdev, int16_t *audioData, uint16_t dataAmount); + + void USBD_Update_Audio_MIC_DESC(uint8_t *desc, + uint8_t ac_itf, + uint8_t as_itf, + uint8_t in_ep, + uint8_t str_idx); + /** + * @} + */ + +#ifdef __cplusplus +} +#endif + + +/** + * @} + */ + +/** + * @} + */ +#endif // __USBD_AUDIO_MIC_H_ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/AUDIO_MIC/Src/usbd_audio_mic.c b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/AUDIO_MIC/Src/usbd_audio_mic.c new file mode 100644 index 0000000..751bdc8 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/AUDIO_MIC/Src/usbd_audio_mic.c @@ -0,0 +1,1008 @@ +/** + ****************************************************************************** + * @file usbd_audio.c + * @author MCD Application Team + * @brief This file provides the Audio core functions. + * + * @verbatim + * + * =================================================================== + * AUDIO Class Description + * =================================================================== + * This driver manages the Audio Class 1.0 following the "USB Device Class Definition for + * Audio Devices V1.0 Mar 18, 98". +* This driver implements the following aspects: +* - Device descriptor management +* - Configuration descriptor management +* - Standard AC Interface Descriptor management +* - 1 Audio Streaming Interface +* - 1 Audio Streaming Endpoint +* - 1 Audio Terminal Input +* - Audio Class-Specific AC Interfaces +* - Audio Class-Specific AS Interfaces +* - AudioControl Requests: mute and volume control +* - Audio Synchronization type: Asynchronous +* - Multiple frequencies and channel number configurable using ad hoc +* init function +* +* The current audio class version supports the following audio features: +* - Pulse Coded Modulation (PCM) format +* - Configurable sampling rate +* - Bit resolution: 16 +* - Configurable Number of channels +* - Volume control +* - Mute/Unmute capability +* - Asynchronous Endpoints +* +* @note This driver has been developed starting from the usbd_audio.c file +* included within the standard Cube Package for STM32F4 +* + * + * @endverbatim + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ + +#include "usbd_audio_mic.h" +#include "usbd_ctlreq.h" + +#define _AUDIO_MIC_EP 0x81 +#define _AUDIO_MIC_AC_ITF_NBR 0x00U +#define _AUDIO_MIC_AS_ITF_NBR 0x01U +#define _AUDIO_MIC_STR_DESC_IDX 0x00U + +uint8_t AUDIO_MIC_EP = _AUDIO_MIC_EP; +uint8_t AUDIO_MIC_AC_ITF_NBR = _AUDIO_MIC_AC_ITF_NBR; +uint8_t AUDIO_MIC_AS_ITF_NBR = _AUDIO_MIC_AS_ITF_NBR; +uint8_t AUDIO_MIC_STR_DESC_IDX = _AUDIO_MIC_STR_DESC_IDX; + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY +* @{ +*/ + +/** @defgroup USBD_AUDIO + + * @{ + */ + +/** @defgroup USBD_AUDIO_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_AUDIO_Private_Defines + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_AUDIO_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_AUDIO_Private_FunctionPrototypes + * @{ + */ +static uint8_t USBD_AUDIO_MIC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_AUDIO_MIC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_AUDIO_MIC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static uint8_t *USBD_AUDIO_MIC_GetCfgDesc(uint16_t *length); +static uint8_t *USBD_AUDIO_MIC_GetDeviceQualifierDesc(uint16_t *length); +static uint8_t USBD_AUDIO_MIC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum); +static uint8_t USBD_AUDIO_MIC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum); +static uint8_t USBD_AUDIO_MIC_EP0_RxReady(USBD_HandleTypeDef *pdev); +static uint8_t USBD_AUDIO_MIC_EP0_TxReady(USBD_HandleTypeDef *pdev); +static uint8_t USBD_AUDIO_MIC_SOF(USBD_HandleTypeDef *pdev); +static uint8_t USBD_AUDIO_MIC_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum); +static uint8_t USBD_AUDIO_MIC_IsoOutIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum); +static void USBD_AUDIO_MIC_REQ_GetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static void USBD_AUDIO_MIC_REQ_SetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static void USBD_AUDIO_MIC_REQ_GetMaximum(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static void USBD_AUDIO_MIC_REQ_GetMinimum(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static void USBD_AUDIO_MIC_REQ_GetResolution(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); + +/** + * @} + */ + +/** @defgroup USBD_AUDIO_Private_Variables + * @{ + */ +/* This dummy buffer with 0 values will be sent when there is no availble data */ +static uint8_t IsocInBuffDummy[48 * 4 * 2]; +static int16_t VOL_CUR; +static USBD_AUDIO_MIC_HandleTypeDef haudioInstance; + +USBD_ClassTypeDef USBD_AUDIO_MIC = + { + USBD_AUDIO_MIC_Init, + USBD_AUDIO_MIC_DeInit, + USBD_AUDIO_MIC_Setup, + USBD_AUDIO_MIC_EP0_TxReady, + USBD_AUDIO_MIC_EP0_RxReady, + USBD_AUDIO_MIC_DataIn, + USBD_AUDIO_MIC_DataOut, + USBD_AUDIO_MIC_SOF, + USBD_AUDIO_MIC_IsoINIncomplete, + USBD_AUDIO_MIC_IsoOutIncomplete, + USBD_AUDIO_MIC_GetCfgDesc, + USBD_AUDIO_MIC_GetCfgDesc, + USBD_AUDIO_MIC_GetCfgDesc, + USBD_AUDIO_MIC_GetDeviceQualifierDesc, +}; + +/* USB AUDIO device Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_AUDIO_MIC_CfgDesc[USBD_AUDIO_MIC_CONFIG_DESC_SIZE] __ALIGN_END = + { + /* Configuration 1 */ + 0x09, /* bLength */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType */ + LOBYTE(USBD_AUDIO_MIC_CONFIG_DESC_SIZE), /* wTotalLength: Total size of the Config descriptor */ + HIBYTE(USBD_AUDIO_MIC_CONFIG_DESC_SIZE), + 0x02, /* bNumInterfaces */ + 0x01, /* bConfigurationValue */ + 0x00, /* iConfiguration */ +#if (USBD_SELF_POWERED == 1U) + 0xC0, /* bmAttributes: Bus Powered according to user configuration */ +#else + 0x80, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* bMaxPower = 100 mA */ + /* 09 byte*/ + + /******** IAD to associate the two MIC interfaces */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _AUDIO_MIC_AC_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + USB_DEVICE_CLASS_AUDIO, /* bFunctionClass */ + AUDIO_SUBCLASS_AUDIOCONTROL, /* bFunctionSubClass */ + AUDIO_PROTOCOL_UNDEFINED, /* bFunctionProtocol */ + 0x00, /* iFunction (Index of string descriptor describing this function) */ + /* 17 byte*/ + + /* USB Microphone Standard interface descriptor */ + AUDIO_INTERFACE_DESC_SIZE, /* bLength */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType */ + _AUDIO_MIC_AC_ITF_NBR, /* bInterfaceNumber */ + 0x00, /* bAlternateSetting */ + 0x00, /* bNumEndpoints */ + USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ + AUDIO_SUBCLASS_AUDIOCONTROL, /* bInterfaceSubClass */ + AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ + _AUDIO_MIC_STR_DESC_IDX, /* iInterface */ + /* 26 byte*/ + + /* USB Microphone Class-specific AC Interface Descriptor */ + AUDIO_INTERFACE_DESC_SIZE, /* bLength */ + AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ + AUDIO_CONTROL_HEADER, /* bDescriptorSubtype */ + 0x00, /* 1.00 */ /* bcdADC */ + 0x01, + 0x25 + AUDIO_MIC_CHANNELS, /* wTotalLength = 37+AUDIO_CHANNELS*/ + 0x00, + 0x01, /* bInCollection */ + _AUDIO_MIC_AS_ITF_NBR, /* baInterfaceNr */ + /* 35 byte*/ + + /* USB Microphone Input Terminal Descriptor */ + AUDIO_INPUT_TERMINAL_DESC_SIZE, /* bLength */ + AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ + AUDIO_CONTROL_INPUT_TERMINAL, /* bDescriptorSubtype */ + AUDIO_MIC_TERMINAL_ID, /* bTerminalID */ + 0x01, /* wTerminalType AUDIO_TERMINAL_USB_MICROPHONE 0x0201 */ + 0x02, + 0x00, /* bAssocTerminal */ + AUDIO_MIC_CHANNELS, /* bNrChannels */ +#if (AUDIO_MIC_CHANNELS == 1) + 0x00, /* wChannelConfig 0x0000 Mono */ + 0x00, +#else + 0x03, /* wChannelConfig 0x0003 Stereo */ + 0x00, +#endif + 0x00, /* iChannelNames */ + 0x00, /* iTerminal */ + /* 47 byte*/ + + /* USB Microphone Audio Feature Unit Descriptor */ + 0x07 + AUDIO_MIC_CHANNELS + 1, /* bLength */ + AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ + AUDIO_CONTROL_FEATURE_UNIT, /* bDescriptorSubtype */ + AUDIO_MIC_FU_ID, /* bUnitID */ + 0x01, /* bSourceID */ + 0x01, /* bControlSize */ + +#if (AUDIO_MIC_CHANNELS == 1) + 0x02, + 0x00, +#else + 0x00, + 0x02, + 0x02, +#endif + +#if (AUDIO_MIC_CHANNELS > 2) + 0x02, +#endif + +#if (AUDIO_MIC_CHANNELS > 3) + 0x02, +#endif + +#if (AUDIO_MIC_CHANNELS > 4) + 0x02, +#endif + +#if (AUDIO_MIC_CHANNELS > 5) + 0x02, +#endif + +#if (AUDIO_MIC_CHANNELS > 6) + 0x02, +#endif + +#if (AUDIO_MIC_CHANNELS > 7) + 0x02, +#endif + 0x00, /* iTerminal */ + //55 + AUDIO_MIC_CHANNELS byte + + /*USB Microphone Output Terminal Descriptor */ + 0x09, /* bLength */ + AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ + AUDIO_CONTROL_OUTPUT_TERMINAL, /* bDescriptorSubtype */ + AUDIO_MIC_OUT_TERMINAL_ID, /* bTerminalID */ + 0x01, /* wTerminalType AUDIO_TERMINAL_USB_STREAMING 0x0101*/ + 0x01, + 0x00, + 0x02, + 0x00, + //64 + AUDIO_MIC_CHANNELS byte + + /* USB Microphone Standard AS Interface Descriptor - Audio Streaming Zero Bandwith */ + /* Interface 1, Alternate Setting 0 */ + 0x09, /* bLength */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType */ + _AUDIO_MIC_AS_ITF_NBR, /* bInterfaceNumber */ + 0x00, /* bAlternateSetting */ + 0x00, /* bNumEndpoints */ + USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ + AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ + AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ + 0x00, /* iInterface */ + //73 + AUDIO_MIC_CHANNELS byte + + /* USB Microphone Standard AS Interface Descriptor - Audio Streaming Operational */ + /* Interface 1, Alternate Setting 1 */ + 0x09, /* bLength */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType */ + _AUDIO_MIC_AS_ITF_NBR, /* bInterfaceNumber */ + 0x01, /* bAlternateSetting */ + 0x01, /* bNumEndpoints */ + USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ + AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ + AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ + 0x00, /* iInterface */ + //82 + AUDIO_MIC_CHANNELS byte + + /* USB Microphone Audio Streaming Interface Descriptor */ + AUDIO_STREAMING_INTERFACE_DESC_SIZE, /* bLength */ + AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ + AUDIO_STREAMING_GENERAL, /* bDescriptorSubtype */ + 0x03, /* bTerminalLink */ + 0x01, /* bDelay */ + 0x01, /* wFormatTag AUDIO_FORMAT_PCM 0x0001*/ + 0x00, + //89 + AUDIO_MIC_CHANNELS byte + + /* USB Microphone Audio Type I Format Interface Descriptor */ + 0x0B, /* bLength */ + AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ + AUDIO_STREAMING_FORMAT_TYPE, /* bDescriptorSubtype */ + AUDIO_FORMAT_TYPE_I, /* bFormatType */ + AUDIO_MIC_CHANNELS, /* bNrChannels */ + 0x02, /* bSubFrameSize */ + 16, /* bBitResolution */ + 0x01, /* bSamFreqType */ + AUDIO_MIC_SMPL_FREQ & 0xff, /* tSamFreq 8000 = 0x1F40 */ + (AUDIO_MIC_SMPL_FREQ >> 8) & 0xff, + AUDIO_MIC_SMPL_FREQ >> 16, + //100 + AUDIO_MIC_CHANNELS byte + + /* Endpoint 1 - Standard Descriptor */ + AUDIO_STANDARD_ENDPOINT_DESC_SIZE, /* bLength */ + 0x05, /* bDescriptorType */ + _AUDIO_MIC_EP, /* bEndpointAddress 1 in endpoint*/ + 0x05, /* bmAttributes */ + ((AUDIO_MIC_SMPL_FREQ / 1000 + 2) * AUDIO_MIC_CHANNELS * 2) & 0xFF, /* wMaxPacketSize */ + ((AUDIO_MIC_SMPL_FREQ / 1000 + 2) * AUDIO_MIC_CHANNELS * 2) >> 8, + 0x01, /* bInterval */ + 0x00, /* bRefresh */ + 0x00, /* bSynchAddress */ + //109 + AUDIO_MIC_CHANNELS byte + + /* Endpoint - Audio Streaming Descriptor*/ + AUDIO_STREAMING_ENDPOINT_DESC_SIZE, /* bLength */ + AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ + AUDIO_ENDPOINT_GENERAL, /* bDescriptor */ + 0x00, /* bmAttributes */ + 0x00, /* bLockDelayUnits */ + 0x00, /* wLockDelay */ + 0x00, + //116 + AUDIO_MIC_CHANNELS byte +}; + +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_AUDIO_MIC_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_AUDIO_Private_Functions + * @{ + */ + +/** + * @brief USBD_AUDIO_Init + * Initialize the AUDIO interface + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_AUDIO_MIC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + if (haudioInstance.state != STATE_USB_WAITING_FOR_INIT) + { + return USBD_FAIL; + } + + USBD_AUDIO_MIC_HandleTypeDef *haudio; + pdev->pClassData_UAC_MIC = &haudioInstance; + haudio = (USBD_AUDIO_MIC_HandleTypeDef *)pdev->pClassData_UAC_MIC; + if (haudio->paketDimension == 0) + { + haudio->paketDimension = 1; + } + uint16_t packet_dim = haudio->paketDimension; + uint16_t wr_rd_offset = (AUDIO_MIC_PACKET_NUM / 2) * haudio->dataAmount / haudio->paketDimension; + haudio->wr_ptr = wr_rd_offset * packet_dim; + haudio->rd_ptr = 0; + haudio->timeout = 0; + + ((USBD_AUDIO_MIC_ItfTypeDef *)pdev->pUserData_UAC_MIC)->Init(haudio->frequency, 0, haudio->channels); + + USBD_LL_OpenEP(pdev, + AUDIO_MIC_EP, + USBD_EP_TYPE_ISOC, + AUDIO_MIC_PACKET); + + USBD_LL_FlushEP(pdev, AUDIO_MIC_EP); + + USBD_LL_Transmit(pdev, AUDIO_MIC_EP, + IsocInBuffDummy, + packet_dim); + + haudio->state = STATE_USB_IDLE; + return USBD_OK; +} + +/** + * @brief USBD_AUDIO_Init + * DeInitialize the AUDIO layer + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_AUDIO_MIC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + /* Close EP IN */ + USBD_LL_CloseEP(pdev, AUDIO_MIC_EP); + /* DeInit physical Interface components */ + if (pdev->pClassData_UAC_MIC != NULL) + { + ((USBD_AUDIO_MIC_ItfTypeDef *)pdev->pUserData_UAC_MIC)->DeInit(0); + haudioInstance.state = STATE_USB_WAITING_FOR_INIT; + } + return USBD_OK; +} + +/** + * @brief USBD_AUDIO_Setup + * Handle the AUDIO specific requests + * @param pdev: instance + * @param req: usb requests + * @retval status + */ +static uint8_t USBD_AUDIO_MIC_Setup(USBD_HandleTypeDef *pdev, + USBD_SetupReqTypedef *req) +{ + USBD_AUDIO_MIC_HandleTypeDef *haudio; + uint16_t len; + uint8_t *pbuf; + uint16_t status_info = 0U; + USBD_StatusTypeDef ret = USBD_OK; + + haudio = (USBD_AUDIO_MIC_HandleTypeDef *)pdev->pClassData_UAC_MIC; + + if (haudio == NULL) + { + return (uint8_t)USBD_FAIL; + } + + switch (req->bmRequest & USB_REQ_TYPE_MASK) + { + case USB_REQ_TYPE_CLASS: + switch (req->bRequest) + { + case AUDIO_REQ_GET_CUR: + USBD_AUDIO_MIC_REQ_GetCurrent(pdev, req); + break; + + case AUDIO_REQ_SET_CUR: + USBD_AUDIO_MIC_REQ_SetCurrent(pdev, req); + break; + + case AUDIO_REQ_GET_MIN: + USBD_AUDIO_MIC_REQ_GetMinimum(pdev, req); + break; + + case AUDIO_REQ_GET_MAX: + USBD_AUDIO_MIC_REQ_GetMaximum(pdev, req); + break; + + case AUDIO_REQ_GET_RES: + USBD_AUDIO_MIC_REQ_GetResolution(pdev, req); + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + break; + + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) + { + case USB_REQ_GET_STATUS: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_GET_DESCRIPTOR: + if ((req->wValue >> 8) == AUDIO_DESCRIPTOR_TYPE) + { + + pbuf = USBD_AUDIO_MIC_CfgDesc + 18; + len = MIN(USBD_AUDIO_MIC_CONFIG_DESC_SIZE, req->wLength); + + (void)USBD_CtlSendData(pdev, pbuf, len); + } + break; + + case USB_REQ_GET_INTERFACE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, (uint8_t *)&haudio->alt_setting, 1U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_SET_INTERFACE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + if ((uint8_t)(req->wValue) <= USBD_MAX_NUM_INTERFACES) + { + haudio->alt_setting = (uint8_t)(req->wValue); + } + else + { + /* Call the error management function (command will be NAKed */ + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_CLEAR_FEATURE: + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + break; + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + + return (uint8_t)ret; +} + +/** + * @brief USBD_AUDIO_GetCfgDesc + * return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_AUDIO_MIC_GetCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_AUDIO_MIC_CfgDesc); + + return USBD_AUDIO_MIC_CfgDesc; +} + +uint16_t app; +uint16_t rd_ptr; +uint16_t wr_ptr; +/** + * @brief USBD_AUDIO_DataIn + * handle data IN Stage + * @param pdev: device instance + * @param epnum: endpoint index + * @retval status + */ +static uint8_t USBD_AUDIO_MIC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + + USBD_AUDIO_MIC_HandleTypeDef *haudio; + + haudio = pdev->pClassData_UAC_MIC; + + rd_ptr = haudio->rd_ptr; + wr_ptr = haudio->wr_ptr; + + uint32_t length_usb_pck; + // uint16_t app; + uint16_t IsocInWr_app = haudio->wr_ptr; + uint16_t true_dim = haudio->buffer_length; + uint16_t packet_dim = haudio->paketDimension; + uint16_t channels = haudio->channels; + length_usb_pck = packet_dim; + haudio->timeout = 0; + if (epnum == (AUDIO_MIC_EP & 0x7F)) + { + if (haudio->state == STATE_USB_IDLE) + { + haudio->state = STATE_USB_REQUESTS_STARTED; + ((USBD_AUDIO_MIC_ItfTypeDef *)pdev->pUserData_UAC_MIC)->Record(); + } + if (haudio->state == STATE_USB_BUFFER_WRITE_STARTED) + { + haudio->rd_ptr = haudio->rd_ptr % (true_dim); + if (IsocInWr_app < haudio->rd_ptr) + { + app = ((true_dim)-haudio->rd_ptr) + IsocInWr_app; + } + else + { + app = IsocInWr_app - haudio->rd_ptr; + } + if (app >= (packet_dim * haudio->upper_treshold)) + { + length_usb_pck += channels * 2; + } + else if (app <= (packet_dim * haudio->lower_treshold)) + { + length_usb_pck -= channels * 2; + } + USBD_LL_Transmit(pdev, AUDIO_MIC_EP, + (uint8_t *)(&haudio->buffer[haudio->rd_ptr]), + length_usb_pck); + haudio->rd_ptr += length_usb_pck; + + if (app < haudio->buffer_length / 10) + { + ((USBD_AUDIO_MIC_ItfTypeDef *)pdev->pUserData_UAC_MIC)->Stop(); + haudio->state = STATE_USB_IDLE; + haudio->timeout = 0; + memset(haudio->buffer, 0, (haudio->buffer_length + haudio->dataAmount)); + } + } + else + { + USBD_LL_Transmit(pdev, AUDIO_MIC_EP, + IsocInBuffDummy, + length_usb_pck); + } + } + return USBD_OK; +} + +/** +* @brief USBD_AUDIO_EP0_RxReady +* handle EP0 Rx Ready event +* @param pdev: device instance +* @retval status +*/ + +static uint8_t USBD_AUDIO_MIC_EP0_RxReady(USBD_HandleTypeDef *pdev) +{ + USBD_AUDIO_MIC_HandleTypeDef *haudio; + haudio = pdev->pClassData_UAC_MIC; + if (haudio->control.cmd == AUDIO_REQ_SET_CUR) + { + if (haudio->control.unit == AUDIO_STREAMING_CTRL) + { + ((USBD_AUDIO_MIC_ItfTypeDef *)pdev->pUserData_UAC_MIC)->VolumeCtl(VOL_CUR); + + haudio->control.cmd = 0; + haudio->control.len = 0; + haudio->control.unit = 0; + haudio->control.data[0] = 0; + haudio->control.data[0] = 0; + } + } + return USBD_OK; +} +/** +* @brief USBD_AUDIO_EP0_TxReady +* handle EP0 TRx Ready event +* @param pdev: device instance +* @retval status +*/ +static uint8_t USBD_AUDIO_MIC_EP0_TxReady(USBD_HandleTypeDef *pdev) +{ + /* Only OUT control data are processed */ + return USBD_OK; +} +/** +* @brief USBD_AUDIO_SOF +* handle SOF event +* @param pdev: device instance +* @retval status +*/ +static uint8_t USBD_AUDIO_MIC_SOF(USBD_HandleTypeDef *pdev) +{ + return USBD_OK; +} + +/** + * @brief USBD_AUDIO_IsoINIncomplete + * handle data ISO IN Incomplete event + * @param pdev: device instance + * @param epnum: endpoint index + * @retval status + */ +static uint8_t USBD_AUDIO_MIC_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + UNUSED(pdev); + UNUSED(epnum); + + return (uint8_t)USBD_OK; +} +/** + * @brief USBD_AUDIO_IsoOutIncomplete + * handle data ISO OUT Incomplete event + * @param pdev: device instance + * @param epnum: endpoint index + * @retval status + */ +static uint8_t USBD_AUDIO_MIC_IsoOutIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + UNUSED(pdev); + UNUSED(epnum); + + return (uint8_t)USBD_OK; +} +/** +* @brief USBD_AUDIO_DataOut +* handle data OUT Stage +* @param pdev: device instance +* @param epnum: endpoint index +* @retval status +*/ +static uint8_t USBD_AUDIO_MIC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + return USBD_OK; +} + +/** +* @brief DeviceQualifierDescriptor +* return Device Qualifier descriptor +* @param length : pointer data length +* @retval pointer to descriptor buffer +*/ +static uint8_t *USBD_AUDIO_MIC_GetDeviceQualifierDesc(uint16_t *length) +{ + *length = sizeof(USBD_AUDIO_MIC_DeviceQualifierDesc); + return USBD_AUDIO_MIC_DeviceQualifierDesc; +} + +/** +* @brief AUDIO_REQ_GetMaximum +* Handles the VOL_MAX Audio control request. +* @param pdev: instance +* @param req: setup class request +* @retval status +*/ +static void USBD_AUDIO_MIC_REQ_GetMaximum(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_AUDIO_MIC_HandleTypeDef *haudio; + haudio = pdev->pClassData_UAC_MIC; + + (haudio->control.data)[0] = (uint16_t)AUDIO_MIC_VOL_MAX & 0xFF; + (haudio->control.data)[1] = ((uint16_t)AUDIO_MIC_VOL_MAX & 0xFF00) >> 8; + + USBD_CtlSendData(pdev, + haudio->control.data, + req->wLength); +} + +/** +* @brief AUDIO_REQ_GetMinimum +* Handles the VOL_MIN Audio control request. +* @param pdev: instance +* @param req: setup class request +* @retval status +*/ +static void USBD_AUDIO_MIC_REQ_GetMinimum(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_AUDIO_MIC_HandleTypeDef *haudio; + haudio = pdev->pClassData_UAC_MIC; + (haudio->control.data)[0] = (uint16_t)AUDIO_MIC_VOL_MIN & 0xFF; + (haudio->control.data)[1] = ((uint16_t)AUDIO_MIC_VOL_MIN & 0xFF00) >> 8; + /* Send the current mute state */ + USBD_CtlSendData(pdev, + haudio->control.data, + req->wLength); +} + +/** +* @brief AUDIO_Req_GetResolution +* Handles the VOL_RES Audio control request. +* @param pdev: instance +* @param req: setup class request +* @retval status +*/ +static void USBD_AUDIO_MIC_REQ_GetResolution(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_AUDIO_MIC_HandleTypeDef *haudio; + haudio = pdev->pClassData_UAC_MIC; + (haudio->control.data)[0] = (uint16_t)AUDIO_MIC_VOL_RES & 0xFF; + (haudio->control.data)[1] = ((uint16_t)AUDIO_MIC_VOL_RES & 0xFF00) >> 8; + USBD_CtlSendData(pdev, + haudio->control.data, + req->wLength); +} + +/** +* @brief AUDIO_Req_GetCurrent +* Handles the GET_CUR Audio control request. +* @param pdev: instance +* @param req: setup class request +* @retval status +*/ +static void USBD_AUDIO_MIC_REQ_GetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_AUDIO_MIC_HandleTypeDef *haudio; + haudio = pdev->pClassData_UAC_MIC; + + (haudio->control.data)[0] = (uint16_t)VOL_CUR & 0xFF; + (haudio->control.data)[1] = ((uint16_t)VOL_CUR & 0xFF00) >> 8; + + USBD_CtlSendData(pdev, + haudio->control.data, + req->wLength); +} + +/** +* @brief AUDIO_Req_SetCurrent +* Handles the SET_CUR Audio control request. +* @param pdev: instance +* @param req: setup class request +* @retval status +*/ +static void USBD_AUDIO_MIC_REQ_SetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_AUDIO_MIC_HandleTypeDef *haudio; + haudio = pdev->pClassData_UAC_MIC; + if (req->wLength) + { + /* Prepare the reception of the buffer over EP0 */ + USBD_CtlPrepareRx(pdev, + (uint8_t *)&VOL_CUR, + req->wLength); + + haudio->control.cmd = AUDIO_REQ_SET_CUR; /* Set the request value */ + haudio->control.len = req->wLength; /* Set the request data length */ + haudio->control.unit = HIBYTE(req->wIndex); /* Set the request target unit */ + } +} + +/** +* @} +*/ + +/** @defgroup USBD_AUDIO_IN_Exported_Functions +* @{ +*/ + +/** +* @brief USBD_AUDIO_Data_Transfer +* Fills the USB internal buffer with audio data from user +* @param pdev: device instance +* @param audioData: audio data to be sent via USB +* @param dataAmount: number of PCM samples to be copyed +* @note Depending on the calling frequency, a coherent amount of samples must be passed to +* the function. E.g.: assuming a Sampling frequency of 16 KHz and 1 channel, +* you can pass 16 PCM samples if the function is called each millisecond, +* 32 samples if called every 2 milliseconds and so on. +* @retval status +*/ +uint8_t USBD_AUDIO_MIC_Data_Transfer(USBD_HandleTypeDef *pdev, int16_t *audioData, uint16_t PCMSamples) +{ + + USBD_AUDIO_MIC_HandleTypeDef *haudio; + haudio = (USBD_AUDIO_MIC_HandleTypeDef *)pdev->pClassData_UAC_MIC; + + if (haudioInstance.state == STATE_USB_WAITING_FOR_INIT) + { + return USBD_BUSY; + } + uint16_t dataAmount = PCMSamples * 2; /*Bytes*/ + uint16_t true_dim = haudio->buffer_length; + uint16_t current_data_Amount = haudio->dataAmount; + uint16_t packet_dim = haudio->paketDimension; + + if (haudio->state == STATE_USB_REQUESTS_STARTED || current_data_Amount != dataAmount) + { + /*USB parameters definition, based on the amount of data passed*/ + haudio->dataAmount = dataAmount; + uint16_t wr_rd_offset = (AUDIO_MIC_PACKET_NUM / 2) * dataAmount / packet_dim; + haudio->wr_ptr = wr_rd_offset * packet_dim; + haudio->rd_ptr = 0; + haudio->upper_treshold = wr_rd_offset + 1; + haudio->lower_treshold = wr_rd_offset - 1; + haudio->buffer_length = (packet_dim * (dataAmount / packet_dim) * AUDIO_MIC_PACKET_NUM); + + /*Memory allocation for data buffer, depending (also) on data amount passed to the transfer function*/ + if (haudio->buffer != NULL) + { + USBD_free(haudio->buffer); + } + haudio->buffer = USBD_malloc(haudio->buffer_length + haudio->dataAmount); + if (haudio->buffer == NULL) + { + return USBD_FAIL; + } + memset(haudio->buffer, 0, (haudio->buffer_length + haudio->dataAmount)); + haudio->state = STATE_USB_BUFFER_WRITE_STARTED; + } + else if (haudio->state == STATE_USB_BUFFER_WRITE_STARTED) + { + if (haudio->timeout++ == TIMEOUT_VALUE) + { + haudio->state = STATE_USB_IDLE; + ((USBD_AUDIO_MIC_ItfTypeDef *)pdev->pUserData_UAC_MIC)->Stop(); + haudio->timeout = 0; + } + memcpy((uint8_t *)&haudio->buffer[haudio->wr_ptr], (uint8_t *)(audioData), dataAmount); + haudio->wr_ptr += dataAmount; + haudio->wr_ptr = haudio->wr_ptr % (true_dim); + if ((haudio->wr_ptr - dataAmount) == 0) + { + memcpy((uint8_t *)(((uint8_t *)haudio->buffer) + true_dim), (uint8_t *)haudio->buffer, dataAmount); + } + } + return USBD_OK; +} + +/** + * @brief USBD_AUDIO_RegisterInterface + * @param fops: Audio interface callback + * @retval status + */ +uint8_t USBD_AUDIO_MIC_RegisterInterface(USBD_HandleTypeDef *pdev, + USBD_AUDIO_MIC_ItfTypeDef *fops) +{ + if (fops == NULL) + { + return (uint8_t)USBD_FAIL; + } + + pdev->pUserData_UAC_MIC = fops; + + return (uint8_t)USBD_OK; +} + +void USBD_Update_Audio_MIC_DESC(uint8_t *desc, + uint8_t ac_itf, + uint8_t as_itf, + uint8_t in_ep, + uint8_t str_idx) +{ + desc[11] = ac_itf; + desc[19] = ac_itf; + desc[25] = str_idx; + desc[34] = as_itf; + desc[66 + AUDIO_MIC_CHANNELS] = as_itf; + desc[75 + AUDIO_MIC_CHANNELS] = as_itf; + desc[102 + AUDIO_MIC_CHANNELS] = in_ep; + + AUDIO_MIC_EP = in_ep; + AUDIO_MIC_AC_ITF_NBR = ac_itf; + AUDIO_MIC_AS_ITF_NBR = as_itf; + + AUDIO_MIC_STR_DESC_IDX = str_idx; + + haudioInstance.paketDimension = (AUDIO_MIC_SMPL_FREQ / 1000 * AUDIO_MIC_CHANNELS * 2); + haudioInstance.frequency = AUDIO_MIC_SMPL_FREQ; + haudioInstance.buffer_length = haudioInstance.paketDimension * AUDIO_MIC_PACKET_NUM; + haudioInstance.channels = AUDIO_MIC_CHANNELS; + haudioInstance.upper_treshold = 5; + haudioInstance.lower_treshold = 2; + haudioInstance.state = STATE_USB_WAITING_FOR_INIT; + haudioInstance.wr_ptr = 3 * haudioInstance.paketDimension; + haudioInstance.rd_ptr = 0; + haudioInstance.dataAmount = 0; + haudioInstance.buffer = 0; +} + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/AUDIO_SPKR/Inc/usbd_audio_spkr.h b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/AUDIO_SPKR/Inc/usbd_audio_spkr.h new file mode 100644 index 0000000..fe0d696 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/AUDIO_SPKR/Inc/usbd_audio_spkr.h @@ -0,0 +1,143 @@ +/** + ****************************************************************************** + * @file usbd_audio.h + * @author MCD Application Team + * @brief header file for the usbd_audio.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_AUDIO_SPKR_H +#define __USB_AUDIO_SPKR_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ioreq.h" +#include "usbd_audio.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_AUDIO + * @brief This file is the Header file for usbd_audio.c + * @{ + */ + + +/** @defgroup USBD_AUDIO_Exported_Defines + * @{ + */ + +#define AUDIO_SPKR_STR_DESC "STM32 SPEAKER" + +#define USBD_AUDIO_FREQ 16000U + +#define USBD_AUDIO_SPKR_CONFIG_DESC_SIZE 117 + +#define AUDIO_OUT_TC 0x01U +#define AUDIO_IN_TC 0x02U + + +#define AUDIO_OUT_PACKET (uint16_t)(((USBD_AUDIO_FREQ * 2U * 2U) / 1000U)) +#define AUDIO_DEFAULT_VOLUME 70U + +/* Number of sub-packets in the audio transfer buffer. You can modify this value but always make sure + that it is an even number and higher than 3 */ +#define AUDIO_OUT_PACKET_NUM 80U +/* Total size of the audio transfer buffer */ +#define AUDIO_TOTAL_BUF_SIZE ((uint16_t)(AUDIO_OUT_PACKET * AUDIO_OUT_PACKET_NUM)) + + typedef struct + { + uint32_t alt_setting; + uint8_t buffer[AUDIO_TOTAL_BUF_SIZE]; + AUDIO_OffsetTypeDef offset; + uint8_t rd_enable; + uint16_t rd_ptr; + uint16_t wr_ptr; + USBD_AUDIO_ControlTypeDef control; + } USBD_AUDIO_SPKR_HandleTypeDef; + + typedef struct + { + int8_t (*Init)(uint32_t AudioFreq, uint32_t Volume, uint32_t options); + int8_t (*DeInit)(uint32_t options); + int8_t (*AudioCmd)(uint8_t *pbuf, uint32_t size, uint8_t cmd); + int8_t (*VolumeCtl)(uint8_t vol); + int8_t (*MuteCtl)(uint8_t cmd); + int8_t (*PeriodicTC)(uint8_t *pbuf, uint32_t size, uint8_t cmd); + int8_t (*GetState)(void); + } USBD_AUDIO_SPKR_ItfTypeDef; + /** + * @} + */ + + /** @defgroup USBD_CORE_Exported_Macros + * @{ + */ + + /** + * @} + */ + + /** @defgroup USBD_CORE_Exported_Variables + * @{ + */ + + extern USBD_ClassTypeDef USBD_AUDIO_SPKR; + + extern uint8_t AUDIO_SPKR_EP; + extern uint8_t AUDIO_SPKR_AC_ITF_NBR; + extern uint8_t AUDIO_SPKR_AS_ITF_NBR; + extern uint8_t AUDIO_SPKR_STR_DESC_IDX; + + /** + * @} + */ + + /** @defgroup USB_CORE_Exported_Functions + * @{ + */ + uint8_t USBD_AUDIO_SPKR_RegisterInterface(USBD_HandleTypeDef *pdev, + USBD_AUDIO_SPKR_ItfTypeDef *fops); + + void USBD_AUDIO_SPKR_Sync(USBD_HandleTypeDef *pdev, AUDIO_OffsetTypeDef offset); + + void USBD_Update_Audio_SPKR_DESC(uint8_t *desc, + uint8_t ac_itf, + uint8_t as_itf, + uint8_t out_ep, + uint8_t str_idx); + /** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_AUDIO_SPKR_H */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/AUDIO_SPKR/Src/usbd_audio_spkr.c b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/AUDIO_SPKR/Src/usbd_audio_spkr.c new file mode 100644 index 0000000..2fdf361 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/AUDIO_SPKR/Src/usbd_audio_spkr.c @@ -0,0 +1,895 @@ +/** + ****************************************************************************** + * @file usbd_audio.c + * @author MCD Application Team + * @brief This file provides the Audio core functions. + * + * @verbatim + * + * =================================================================== + * AUDIO Class Description + * =================================================================== + * This driver manages the Audio Class 1.0 following the "USB Device Class Definition for + * Audio Devices V1.0 Mar 18, 98". + * This driver implements the following aspects of the specification: + * - Device descriptor management + * - Configuration descriptor management + * - Standard AC Interface Descriptor management + * - 1 Audio Streaming Interface (with single channel, PCM, Stereo mode) + * - 1 Audio Streaming Endpoint + * - 1 Audio Terminal Input (1 channel) + * - Audio Class-Specific AC Interfaces + * - Audio Class-Specific AS Interfaces + * - AudioControl Requests: only SET_CUR and GET_CUR requests are supported (for Mute) + * - Audio Feature Unit (limited to Mute control) + * - Audio Synchronization type: Asynchronous + * - Single fixed audio sampling rate (configurable in usbd_conf.h file) + * The current audio class version supports the following audio features: + * - Pulse Coded Modulation (PCM) format + * - sampling rate: 48KHz. + * - Bit resolution: 16 + * - Number of channels: 2 + * - No volume control + * - Mute/Unmute capability + * - Asynchronous Endpoints + * + * @note In HS mode and when the DMA is used, all variables and data structures + * dealing with the DMA during the transaction process should be 32-bit aligned. + * + * + * @endverbatim + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ + +#include "usbd_audio_spkr.h" +#include "usbd_ctlreq.h" + +#define _AUDIO_SPKR_EP 0x01U +#define _AUDIO_SPKR_AC_ITF_NBR 0x00U +#define _AUDIO_SPKR_AS_ITF_NBR 0x01U +#define _AUDIO_SPKR_STR_DESC_IDX 0x00U + +uint8_t AUDIO_SPKR_EP = _AUDIO_SPKR_EP; +uint8_t AUDIO_SPKR_AC_ITF_NBR = _AUDIO_SPKR_AC_ITF_NBR; +uint8_t AUDIO_SPKR_AS_ITF_NBR = _AUDIO_SPKR_AS_ITF_NBR; +uint8_t AUDIO_SPKR_STR_DESC_IDX = _AUDIO_SPKR_STR_DESC_IDX; + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY +* @{ +*/ + +/** @defgroup USBD_AUDIO + + * @{ + */ + +/** @defgroup USBD_AUDIO_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_AUDIO_Private_Defines + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_AUDIO_Private_Macros + * @{ + */ +#define AUDIO_SAMPLE_FREQ(frq) (uint8_t)(frq), (uint8_t)((frq >> 8)), (uint8_t)((frq >> 16)) + +#define AUDIO_PACKET_SZE(frq) (uint8_t)(((frq * 2U * 2U) / 1000U) & 0xFFU), \ + (uint8_t)((((frq * 2U * 2U) / 1000U) >> 8) & 0xFFU) + +/** + * @} + */ + +/** @defgroup USBD_AUDIO_Private_FunctionPrototypes + * @{ + */ +static uint8_t USBD_AUDIO_SPKR_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_AUDIO_SPKR_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_AUDIO_SPKR_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static uint8_t *USBD_AUDIO_SPKR_GetCfgDesc(uint16_t *length); +static uint8_t *USBD_AUDIO_SPKR_GetDeviceQualifierDesc(uint16_t *length); +static uint8_t USBD_AUDIO_SPKR_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum); +static uint8_t USBD_AUDIO_SPKR_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum); +static uint8_t USBD_AUDIO_SPKR_EP0_RxReady(USBD_HandleTypeDef *pdev); +static uint8_t USBD_AUDIO_SPKR_EP0_TxReady(USBD_HandleTypeDef *pdev); +static uint8_t USBD_AUDIO_SPKR_SOF(USBD_HandleTypeDef *pdev); +static uint8_t USBD_AUDIO_SPKR_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum); +static uint8_t USBD_AUDIO_SPKR_IsoOutIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum); +static void USBD_AUDIO_SPKR_REQ_GetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static void USBD_AUDIO_SPKR_REQ_SetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); + +/** + * @} + */ + +/** @defgroup USBD_AUDIO_Private_Variables + * @{ + */ + +static USBD_AUDIO_SPKR_HandleTypeDef haudioInstance; + +USBD_ClassTypeDef USBD_AUDIO_SPKR = + { + USBD_AUDIO_SPKR_Init, + USBD_AUDIO_SPKR_DeInit, + USBD_AUDIO_SPKR_Setup, + USBD_AUDIO_SPKR_EP0_TxReady, + USBD_AUDIO_SPKR_EP0_RxReady, + USBD_AUDIO_SPKR_DataIn, + USBD_AUDIO_SPKR_DataOut, + USBD_AUDIO_SPKR_SOF, + USBD_AUDIO_SPKR_IsoINIncomplete, + USBD_AUDIO_SPKR_IsoOutIncomplete, + USBD_AUDIO_SPKR_GetCfgDesc, + USBD_AUDIO_SPKR_GetCfgDesc, + USBD_AUDIO_SPKR_GetCfgDesc, + USBD_AUDIO_SPKR_GetDeviceQualifierDesc, +}; + +/* USB AUDIO device Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_AUDIO_SPKR_CfgDesc[USBD_AUDIO_SPKR_CONFIG_DESC_SIZE] __ALIGN_END = + { + /* Configuration 1 */ + 0x09, /* bLength */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType */ + LOBYTE(USBD_AUDIO_SPKR_CONFIG_DESC_SIZE), /* wTotalLength 109 bytes*/ + HIBYTE(USBD_AUDIO_SPKR_CONFIG_DESC_SIZE), + 0x02, /* bNumInterfaces */ + 0x01, /* bConfigurationValue */ + 0x00, /* iConfiguration */ +#if (USBD_SELF_POWERED == 1U) + 0xC0, /* bmAttributes: Bus Powered according to user configuration */ +#else + 0x80, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* bMaxPower = 100 mA */ + /* 09 byte*/ + + /******** IAD to associate the two SPKR interfaces */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _AUDIO_SPKR_AC_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + USB_DEVICE_CLASS_AUDIO, /* bFunctionClass */ + AUDIO_SUBCLASS_AUDIOCONTROL, /* bFunctionSubClass */ + AUDIO_PROTOCOL_UNDEFINED, /* bFunctionProtocol */ + 0x00, /* iFunction (Index of string descriptor describing this function) */ + + /* USB Speaker Standard interface descriptor */ + AUDIO_INTERFACE_DESC_SIZE, /* bLength */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType */ + _AUDIO_SPKR_AC_ITF_NBR, /* bInterfaceNumber */ + 0x00, /* bAlternateSetting */ + 0x00, /* bNumEndpoints */ + USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ + AUDIO_SUBCLASS_AUDIOCONTROL, /* bInterfaceSubClass */ + AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ + _AUDIO_SPKR_STR_DESC_IDX, /* iInterface */ + /* 09 byte*/ + + /* USB Speaker Class-specific AC Interface Descriptor */ + AUDIO_INTERFACE_DESC_SIZE, /* bLength */ + AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ + AUDIO_CONTROL_HEADER, /* bDescriptorSubtype */ + 0x00, /* 1.00 */ /* bcdADC */ + 0x01, + 0x27, /* wTotalLength = 39*/ + 0x00, + 0x01, /* bInCollection */ + _AUDIO_SPKR_AS_ITF_NBR, /* baInterfaceNr */ + /* 09 byte*/ + + /* USB Speaker Input Terminal Descriptor */ + AUDIO_INPUT_TERMINAL_DESC_SIZE, /* bLength */ + AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ + AUDIO_CONTROL_INPUT_TERMINAL, /* bDescriptorSubtype */ + 0x01, /* bTerminalID */ + 0x01, /* wTerminalType AUDIO_TERMINAL_USB_STREAMING 0x0101 */ + 0x01, + 0x00, /* bAssocTerminal */ + 0x01, /* bNrChannels */ + 0x00, /* wChannelConfig 0x0000 Mono */ + 0x00, + 0x00, /* iChannelNames */ + 0x00, /* iTerminal */ + /* 12 byte*/ + + /* USB Speaker Audio Feature Unit Descriptor */ + 0x09, /* bLength */ + AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ + AUDIO_CONTROL_FEATURE_UNIT, /* bDescriptorSubtype */ + AUDIO_STREAMING_CTRL, /* bUnitID */ + 0x01, /* bSourceID */ + 0x01, /* bControlSize */ + AUDIO_CONTROL_MUTE, /* bmaControls(0) */ + 0x00, /* bmaControls(1) */ + 0x00, /* iTerminal */ + /* 09 byte*/ + + /*USB Speaker Output Terminal Descriptor */ + 0x09, /* bLength */ + AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ + AUDIO_CONTROL_OUTPUT_TERMINAL, /* bDescriptorSubtype */ + 0x03, /* bTerminalID */ + 0x01, /* wTerminalType 0x0301*/ + 0x03, + 0x00, /* bAssocTerminal */ + 0x02, /* bSourceID */ + 0x00, /* iTerminal */ + /* 09 byte*/ + + /* USB Speaker Standard AS Interface Descriptor - Audio Streaming Zero Bandwidth */ + /* Interface 1, Alternate Setting 0 */ + AUDIO_INTERFACE_DESC_SIZE, /* bLength */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType */ + _AUDIO_SPKR_AS_ITF_NBR, /* bInterfaceNumber */ + 0x00, /* bAlternateSetting */ + 0x00, /* bNumEndpoints */ + USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ + AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ + AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ + 0x00, /* iInterface */ + /* 09 byte*/ + + /* USB Speaker Standard AS Interface Descriptor - Audio Streaming Operational */ + /* Interface 1, Alternate Setting 1 */ + AUDIO_INTERFACE_DESC_SIZE, /* bLength */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType */ + _AUDIO_SPKR_AS_ITF_NBR, /* bInterfaceNumber */ + 0x01, /* bAlternateSetting */ + 0x01, /* bNumEndpoints */ + USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ + AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ + AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ + 0x00, /* iInterface */ + /* 09 byte*/ + + /* USB Speaker Audio Streaming Interface Descriptor */ + AUDIO_STREAMING_INTERFACE_DESC_SIZE, /* bLength */ + AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ + AUDIO_STREAMING_GENERAL, /* bDescriptorSubtype */ + 0x01, /* bTerminalLink */ + 0x01, /* bDelay */ + 0x01, /* wFormatTag AUDIO_FORMAT_PCM 0x0001 */ + 0x00, + /* 07 byte*/ + + /* USB Speaker Audio Type III Format Interface Descriptor */ + 0x0B, /* bLength */ + AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ + AUDIO_STREAMING_FORMAT_TYPE, /* bDescriptorSubtype */ + AUDIO_FORMAT_TYPE_I, /* bFormatType */ + 0x02, /* bNrChannels */ + 0x02, /* bSubFrameSize : 2 Bytes per frame (16bits) */ + 16, /* bBitResolution (16-bits per sample) */ + 0x01, /* bSamFreqType only one frequency supported */ + AUDIO_SAMPLE_FREQ(USBD_AUDIO_FREQ), /* Audio sampling frequency coded on 3 bytes */ + /* 11 byte*/ + + /* Endpoint 1 - Standard Descriptor */ + AUDIO_STANDARD_ENDPOINT_DESC_SIZE, /* bLength */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType */ + _AUDIO_SPKR_EP, /* bEndpointAddress 1 out endpoint */ + USBD_EP_TYPE_ISOC, /* bmAttributes */ + AUDIO_PACKET_SZE(USBD_AUDIO_FREQ), /* wMaxPacketSize in Bytes (Freq(Samples)*2(Stereo)*2(HalfWord)) */ + AUDIO_FS_BINTERVAL, /* bInterval */ + 0x00, /* bRefresh */ + 0x00, /* bSynchAddress */ + /* 09 byte*/ + + /* Endpoint - Audio Streaming Descriptor*/ + AUDIO_STREAMING_ENDPOINT_DESC_SIZE, /* bLength */ + AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ + AUDIO_ENDPOINT_GENERAL, /* bDescriptor */ + 0x00, /* bmAttributes */ + 0x00, /* bLockDelayUnits */ + 0x00, /* wLockDelay */ + 0x00, + /* 07 byte*/ +}; + +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_AUDIO_SPKR_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_AUDIO_Private_Functions + * @{ + */ + +/** + * @brief USBD_AUDIO_Init + * Initialize the AUDIO interface + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_AUDIO_SPKR_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(cfgidx); + USBD_AUDIO_SPKR_HandleTypeDef *haudio; + + /* Allocate Audio structure */ + haudio = &haudioInstance; + + if (haudio == NULL) + { + pdev->pClassData_UAC_SPKR = NULL; + return (uint8_t)USBD_EMEM; + } + + pdev->pClassData_UAC_SPKR = (void *)haudio; + + if (pdev->dev_speed == USBD_SPEED_HIGH) + { + pdev->ep_out[AUDIO_SPKR_EP & 0xFU].bInterval = AUDIO_HS_BINTERVAL; + } + else /* LOW and FULL-speed endpoints */ + { + pdev->ep_out[AUDIO_SPKR_EP & 0xFU].bInterval = AUDIO_FS_BINTERVAL; + } + + /* Open EP OUT */ + (void)USBD_LL_OpenEP(pdev, AUDIO_SPKR_EP, USBD_EP_TYPE_ISOC, AUDIO_OUT_PACKET); + pdev->ep_out[AUDIO_SPKR_EP & 0xFU].is_used = 1U; + + haudio->alt_setting = 0U; + haudio->offset = AUDIO_OFFSET_UNKNOWN; + haudio->wr_ptr = 0U; + haudio->rd_ptr = 0U; + haudio->rd_enable = 0U; + + /* Initialize the Audio output Hardware layer */ + if (((USBD_AUDIO_SPKR_ItfTypeDef *)pdev->pUserData_UAC_SPKR)->Init(USBD_AUDIO_FREQ, AUDIO_DEFAULT_VOLUME, 0U) != 0U) + { + return (uint8_t)USBD_FAIL; + } + + /* Prepare Out endpoint to receive 1st packet */ + (void)USBD_LL_PrepareReceive(pdev, AUDIO_SPKR_EP, haudio->buffer, + AUDIO_OUT_PACKET); + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_AUDIO_Init + * DeInitialize the AUDIO layer + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_AUDIO_SPKR_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(cfgidx); + + /* Open EP OUT */ + (void)USBD_LL_CloseEP(pdev, AUDIO_SPKR_EP); + pdev->ep_out[AUDIO_SPKR_EP & 0xFU].is_used = 0U; + pdev->ep_out[AUDIO_SPKR_EP & 0xFU].bInterval = 0U; + + /* DeInit physical Interface components */ + if (pdev->pClassData_UAC_SPKR != NULL) + { + ((USBD_AUDIO_SPKR_ItfTypeDef *)pdev->pUserData_UAC_SPKR)->DeInit(0U); +#if (0) + (void)USBD_free(pdev->pClassData_UAC_SPKR); +#endif + pdev->pClassData_UAC_SPKR = NULL; + } + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_AUDIO_Setup + * Handle the AUDIO specific requests + * @param pdev: instance + * @param req: usb requests + * @retval status + */ +static uint8_t USBD_AUDIO_SPKR_Setup(USBD_HandleTypeDef *pdev, + USBD_SetupReqTypedef *req) +{ + USBD_AUDIO_SPKR_HandleTypeDef *haudio; + uint16_t len; + uint8_t *pbuf; + uint16_t status_info = 0U; + USBD_StatusTypeDef ret = USBD_OK; + + haudio = (USBD_AUDIO_SPKR_HandleTypeDef *)pdev->pClassData_UAC_SPKR; + + if (haudio == NULL) + { + return (uint8_t)USBD_FAIL; + } + + switch (req->bmRequest & USB_REQ_TYPE_MASK) + { + case USB_REQ_TYPE_CLASS: + switch (req->bRequest) + { + case AUDIO_REQ_GET_CUR: + USBD_AUDIO_SPKR_REQ_GetCurrent(pdev, req); + break; + + case AUDIO_REQ_SET_CUR: + USBD_AUDIO_SPKR_REQ_SetCurrent(pdev, req); + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + break; + + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) + { + case USB_REQ_GET_STATUS: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_GET_DESCRIPTOR: + if ((req->wValue >> 8) == AUDIO_DESCRIPTOR_TYPE) + { + pbuf = USBD_AUDIO_SPKR_CfgDesc + 18; + len = MIN(USBD_AUDIO_SPKR_CONFIG_DESC_SIZE, req->wLength); + + (void)USBD_CtlSendData(pdev, pbuf, len); + } + break; + + case USB_REQ_GET_INTERFACE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, (uint8_t *)&haudio->alt_setting, 1U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_SET_INTERFACE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + if ((uint8_t)(req->wValue) <= USBD_MAX_NUM_INTERFACES) + { + haudio->alt_setting = (uint8_t)(req->wValue); + } + else + { + /* Call the error management function (command will be NAKed */ + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_CLEAR_FEATURE: + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + break; + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + + return (uint8_t)ret; +} + +/** + * @brief USBD_AUDIO_GetCfgDesc + * return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_AUDIO_SPKR_GetCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_AUDIO_SPKR_CfgDesc); + + return USBD_AUDIO_SPKR_CfgDesc; +} + +/** + * @brief USBD_AUDIO_DataIn + * handle data IN Stage + * @param pdev: device instance + * @param epnum: endpoint index + * @retval status + */ +static uint8_t USBD_AUDIO_SPKR_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + UNUSED(pdev); + UNUSED(epnum); + + /* Only OUT data are processed */ + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_AUDIO_EP0_RxReady + * handle EP0 Rx Ready event + * @param pdev: device instance + * @retval status + */ +static uint8_t USBD_AUDIO_SPKR_EP0_RxReady(USBD_HandleTypeDef *pdev) +{ + USBD_AUDIO_SPKR_HandleTypeDef *haudio; + haudio = (USBD_AUDIO_SPKR_HandleTypeDef *)pdev->pClassData_UAC_SPKR; + + if (haudio == NULL) + { + return (uint8_t)USBD_FAIL; + } + + if (haudio->control.cmd == AUDIO_REQ_SET_CUR) + { + /* In this driver, to simplify code, only SET_CUR request is managed */ + + if (haudio->control.unit == AUDIO_STREAMING_CTRL) + { + ((USBD_AUDIO_SPKR_ItfTypeDef *)pdev->pUserData_UAC_SPKR)->MuteCtl(haudio->control.data[0]); + haudio->control.cmd = 0U; + haudio->control.len = 0U; + } + } + + return (uint8_t)USBD_OK; +} +/** + * @brief USBD_AUDIO_EP0_TxReady + * handle EP0 TRx Ready event + * @param pdev: device instance + * @retval status + */ +static uint8_t USBD_AUDIO_SPKR_EP0_TxReady(USBD_HandleTypeDef *pdev) +{ + UNUSED(pdev); + + /* Only OUT control data are processed */ + return (uint8_t)USBD_OK; +} +/** + * @brief USBD_AUDIO_SOF + * handle SOF event + * @param pdev: device instance + * @retval status + */ +static uint8_t USBD_AUDIO_SPKR_SOF(USBD_HandleTypeDef *pdev) +{ + UNUSED(pdev); + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_AUDIO_SOF + * handle SOF event + * @param pdev: device instance + * @retval status + */ +void USBD_AUDIO_SPKR_Sync(USBD_HandleTypeDef *pdev, AUDIO_OffsetTypeDef offset) +{ + USBD_AUDIO_SPKR_HandleTypeDef *haudio; + uint32_t BufferSize = AUDIO_TOTAL_BUF_SIZE / 2U; + + if (pdev->pClassData_UAC_SPKR == NULL) + { + return; + } + + haudio = (USBD_AUDIO_SPKR_HandleTypeDef *)pdev->pClassData_UAC_SPKR; + + haudio->offset = offset; + + if (haudio->rd_enable == 1U) + { + haudio->rd_ptr += (uint16_t)BufferSize; + + if (haudio->rd_ptr == AUDIO_TOTAL_BUF_SIZE) + { + /* roll back */ + haudio->rd_ptr = 0U; + } + } + + if (haudio->rd_ptr > haudio->wr_ptr) + { + if ((haudio->rd_ptr - haudio->wr_ptr) < AUDIO_OUT_PACKET) + { + BufferSize += 4U; + } + else + { + if ((haudio->rd_ptr - haudio->wr_ptr) > (AUDIO_TOTAL_BUF_SIZE - AUDIO_OUT_PACKET)) + { + BufferSize -= 4U; + } + } + } + else + { + if ((haudio->wr_ptr - haudio->rd_ptr) < AUDIO_OUT_PACKET) + { + BufferSize -= 4U; + } + else + { + if ((haudio->wr_ptr - haudio->rd_ptr) > (AUDIO_TOTAL_BUF_SIZE - AUDIO_OUT_PACKET)) + { + BufferSize += 4U; + } + } + } + + if (haudio->offset == AUDIO_OFFSET_FULL) + { + ((USBD_AUDIO_SPKR_ItfTypeDef *)pdev->pUserData_UAC_SPKR)->AudioCmd(&haudio->buffer[0], BufferSize, AUDIO_CMD_PLAY); + haudio->offset = AUDIO_OFFSET_NONE; + } +} + +/** + * @brief USBD_AUDIO_IsoINIncomplete + * handle data ISO IN Incomplete event + * @param pdev: device instance + * @param epnum: endpoint index + * @retval status + */ +static uint8_t USBD_AUDIO_SPKR_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + UNUSED(pdev); + UNUSED(epnum); + + return (uint8_t)USBD_OK; +} +/** + * @brief USBD_AUDIO_IsoOutIncomplete + * handle data ISO OUT Incomplete event + * @param pdev: device instance + * @param epnum: endpoint index + * @retval status + */ +static uint8_t USBD_AUDIO_SPKR_IsoOutIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + UNUSED(pdev); + UNUSED(epnum); + + return (uint8_t)USBD_OK; +} +/** + * @brief USBD_AUDIO_DataOut + * handle data OUT Stage + * @param pdev: device instance + * @param epnum: endpoint index + * @retval status + */ +static uint8_t USBD_AUDIO_SPKR_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + uint16_t PacketSize; + USBD_AUDIO_SPKR_HandleTypeDef *haudio; + + haudio = (USBD_AUDIO_SPKR_HandleTypeDef *)pdev->pClassData_UAC_SPKR; + + if (haudio == NULL) + { + return (uint8_t)USBD_FAIL; + } + + if (epnum == AUDIO_SPKR_EP) + { + /* Get received data packet length */ + PacketSize = (uint16_t)USBD_LL_GetRxDataSize(pdev, epnum); + + /* Packet received Callback */ + ((USBD_AUDIO_SPKR_ItfTypeDef *)pdev->pUserData_UAC_SPKR)->PeriodicTC(&haudio->buffer[haudio->wr_ptr], PacketSize, AUDIO_OUT_TC); + + /* Increment the Buffer pointer or roll it back when all buffers are full */ + haudio->wr_ptr += PacketSize; + + if (haudio->wr_ptr == AUDIO_TOTAL_BUF_SIZE) + { + /* All buffers are full: roll back */ + haudio->wr_ptr = 0U; + + if (haudio->offset == AUDIO_OFFSET_UNKNOWN) + { + ((USBD_AUDIO_SPKR_ItfTypeDef *)pdev->pUserData_UAC_SPKR)->AudioCmd(&haudio->buffer[0], AUDIO_TOTAL_BUF_SIZE / 2U, AUDIO_CMD_START); + haudio->offset = AUDIO_OFFSET_NONE; + } + } + + if (haudio->rd_enable == 0U) + { + if (haudio->wr_ptr == (AUDIO_TOTAL_BUF_SIZE / 2U)) + { + haudio->rd_enable = 1U; + } + } + + /* Prepare Out endpoint to receive next audio packet */ + (void)USBD_LL_PrepareReceive(pdev, AUDIO_SPKR_EP, + &haudio->buffer[haudio->wr_ptr], + AUDIO_OUT_PACKET); + } + + return (uint8_t)USBD_OK; +} + +/** + * @brief AUDIO_Req_GetCurrent + * Handles the GET_CUR Audio control request. + * @param pdev: instance + * @param req: setup class request + * @retval status + */ +static void USBD_AUDIO_SPKR_REQ_GetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_AUDIO_SPKR_HandleTypeDef *haudio; + haudio = (USBD_AUDIO_SPKR_HandleTypeDef *)pdev->pClassData_UAC_SPKR; + + if (haudio == NULL) + { + return; + } + + (void)USBD_memset(haudio->control.data, 0, 64U); + + /* Send the current mute state */ + (void)USBD_CtlSendData(pdev, haudio->control.data, req->wLength); +} + +/** + * @brief AUDIO_Req_SetCurrent + * Handles the SET_CUR Audio control request. + * @param pdev: instance + * @param req: setup class request + * @retval status + */ +static void USBD_AUDIO_SPKR_REQ_SetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_AUDIO_SPKR_HandleTypeDef *haudio; + haudio = (USBD_AUDIO_SPKR_HandleTypeDef *)pdev->pClassData_UAC_SPKR; + + if (haudio == NULL) + { + return; + } + + if (req->wLength != 0U) + { + /* Prepare the reception of the buffer over EP0 */ + (void)USBD_CtlPrepareRx(pdev, haudio->control.data, req->wLength); + + haudio->control.cmd = AUDIO_REQ_SET_CUR; /* Set the request value */ + haudio->control.len = (uint8_t)req->wLength; /* Set the request data length */ + haudio->control.unit = HIBYTE(req->wIndex); /* Set the request target unit */ + } +} + +/** + * @brief DeviceQualifierDescriptor + * return Device Qualifier descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_AUDIO_SPKR_GetDeviceQualifierDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_AUDIO_SPKR_DeviceQualifierDesc); + + return USBD_AUDIO_SPKR_DeviceQualifierDesc; +} + +/** + * @brief USBD_AUDIO_RegisterInterface + * @param fops: Audio interface callback + * @retval status + */ +uint8_t USBD_AUDIO_SPKR_RegisterInterface(USBD_HandleTypeDef *pdev, + USBD_AUDIO_SPKR_ItfTypeDef *fops) +{ + if (fops == NULL) + { + return (uint8_t)USBD_FAIL; + } + + pdev->pUserData_UAC_SPKR = fops; + + return (uint8_t)USBD_OK; +} + +void USBD_Update_Audio_SPKR_DESC(uint8_t *desc, + uint8_t ac_itf, + uint8_t as_itf, + uint8_t out_ep, + uint8_t str_idx) +{ + desc[11] = ac_itf; + desc[19] = ac_itf; + desc[25] = str_idx; + desc[34] = as_itf; + desc[67] = as_itf; + desc[76] = as_itf; + desc[103] = out_ep; + + AUDIO_SPKR_EP = out_ep; + AUDIO_SPKR_AC_ITF_NBR = ac_itf; + AUDIO_SPKR_AS_ITF_NBR = as_itf; + + AUDIO_SPKR_STR_DESC_IDX = str_idx; +} + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/CDC_ACM/Inc/usbd_cdc_acm.h b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/CDC_ACM/Inc/usbd_cdc_acm.h new file mode 100644 index 0000000..f7d6657 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/CDC_ACM/Inc/usbd_cdc_acm.h @@ -0,0 +1,189 @@ +/** + ****************************************************************************** + * @file usbd_cdc.h + * @author MCD Application Team + * @brief header file for the usbd_cdc.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_CDC_H +#define __USB_CDC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ioreq.h" +#include "AL94.I-CUBE-USBD-COMPOSITE_conf.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup usbd_cdc + * @brief This file is the Header file for usbd_cdc.c + * @{ + */ + + +/** @defgroup usbd_cdc_Exported_Defines + * @{ + */ + +#define CDC_ACM_STR_DESC "STM32 CDC ACM%d" + +#define NUMBER_OF_CDC _USBD_CDC_ACM_COUNT +#ifndef CDC_HS_BINTERVAL +#define CDC_HS_BINTERVAL 0x10U +#endif /* CDC_HS_BINTERVAL */ + +#ifndef CDC_FS_BINTERVAL +#define CDC_FS_BINTERVAL 0x10U +#endif /* CDC_FS_BINTERVAL */ + +/* CDC Endpoints parameters: you can fine tune these values depending on the needed baudrates and performance. */ +#define CDC_DATA_HS_MAX_PACKET_SIZE 512U /* Endpoint IN & OUT Packet size */ +#define CDC_DATA_FS_MAX_PACKET_SIZE 64U /* Endpoint IN & OUT Packet size */ +#define CDC_CMD_PACKET_SIZE 8U /* Control Endpoint Packet size */ + +#define USB_CDC_CONFIG_DESC_SIZ (9 + 66 * NUMBER_OF_CDC) +#define CDC_DATA_HS_IN_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE +#define CDC_DATA_HS_OUT_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE + +#define CDC_DATA_FS_IN_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE +#define CDC_DATA_FS_OUT_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE + +#define CDC_REQ_MAX_DATA_SIZE 0x7U +/*---------------------------------------------------------------------*/ +/* CDC definitions */ +/*---------------------------------------------------------------------*/ +#define CDC_SEND_ENCAPSULATED_COMMAND 0x00U +#define CDC_GET_ENCAPSULATED_RESPONSE 0x01U +#define CDC_SET_COMM_FEATURE 0x02U +#define CDC_GET_COMM_FEATURE 0x03U +#define CDC_CLEAR_COMM_FEATURE 0x04U +#define CDC_SET_LINE_CODING 0x20U +#define CDC_GET_LINE_CODING 0x21U +#define CDC_SET_CONTROL_LINE_STATE 0x22U +#define CDC_SEND_BREAK 0x23U + + /** + * @} + */ + + /** @defgroup USBD_CORE_Exported_TypesDefinitions + * @{ + */ + + /** + * @} + */ + typedef struct + { + uint32_t bitrate; + uint8_t format; + uint8_t paritytype; + uint8_t datatype; + } USBD_CDC_ACM_LineCodingTypeDef; + + typedef struct _USBD_CDC_Itf + { + int8_t (*Init)(uint8_t cdc_ch); + int8_t (*DeInit)(uint8_t cdc_ch); + int8_t (*Control)(uint8_t cdc_ch, uint8_t cmd, uint8_t *pbuf, uint16_t length); + int8_t (*Receive)(uint8_t cdc_ch, uint8_t *Buf, uint32_t *Len); + int8_t (*TransmitCplt)(uint8_t cdc_ch, uint8_t *Buf, uint32_t *Len, uint8_t epnum); + } USBD_CDC_ACM_ItfTypeDef; + + typedef struct + { + uint32_t data[NUMBER_OF_CDC][CDC_DATA_HS_MAX_PACKET_SIZE / 4U]; /* Force 32bits alignment */ + uint8_t CmdOpCode; + uint8_t CmdLength; + uint8_t *RxBuffer; + uint8_t *TxBuffer; + uint32_t RxLength; + uint32_t TxLength; + + __IO uint32_t TxState; + __IO uint32_t RxState; + } USBD_CDC_ACM_HandleTypeDef; + + /** @defgroup USBD_CORE_Exported_Macros + * @{ + */ + + /** + * @} + */ + + /** @defgroup USBD_CORE_Exported_Variables + * @{ + */ + + extern USBD_ClassTypeDef USBD_CDC_ACM; + + extern uint8_t CDC_IN_EP[NUMBER_OF_CDC]; /* EP1 for data IN */ + extern uint8_t CDC_OUT_EP[NUMBER_OF_CDC]; /* EP1 for data OUT */ + extern uint8_t CDC_CMD_EP[NUMBER_OF_CDC]; /* EP2 for CDC commands */ + + extern uint8_t CDC_CMD_ITF_NBR[NUMBER_OF_CDC]; /* Command Interface Number */ + extern uint8_t CDC_COM_ITF_NBR[NUMBER_OF_CDC]; /* Communication Interface Number */ + + extern uint8_t CDC_STR_DESC_IDX[NUMBER_OF_CDC]; + + /** + * @} + */ + + /** @defgroup USB_CORE_Exported_Functions + * @{ + */ + uint8_t USBD_CDC_ACM_RegisterInterface(USBD_HandleTypeDef *pdev, + USBD_CDC_ACM_ItfTypeDef *fops); + + uint8_t USBD_CDC_SetTxBuffer(uint8_t ch, USBD_HandleTypeDef *pdev, uint8_t *pbuff, + uint32_t length); + + uint8_t USBD_CDC_SetRxBuffer(uint8_t ch, USBD_HandleTypeDef *pdev, uint8_t *pbuff); + uint8_t USBD_CDC_ReceivePacket(uint8_t ch, USBD_HandleTypeDef *pdev); + uint8_t USBD_CDC_TransmitPacket(uint8_t ch, USBD_HandleTypeDef *pdev); + + void USBD_Update_CDC_ACM_DESC(uint8_t *desc, + uint8_t cmd_itf, + uint8_t com_itf, + uint8_t in_ep, + uint8_t cmd_ep, + uint8_t out_ep, + uint8_t str_idx); + /** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_CDC_H */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/CDC_ACM/Src/usbd_cdc_acm.c b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/CDC_ACM/Src/usbd_cdc_acm.c new file mode 100644 index 0000000..b5f85d5 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/CDC_ACM/Src/usbd_cdc_acm.c @@ -0,0 +1,2209 @@ +/** + ****************************************************************************** + * @file usbd_cdc.c + * @author MCD Application Team + * @brief This file provides the high layer firmware functions to manage the + * following functionalities of the USB CDC Class: + * - Initialization and Configuration of high and low layer + * - Enumeration as CDC Device (and enumeration for each implemented memory interface) + * - OUT/IN data transfer + * - Command IN transfer (class requests management) + * - Error management + * + * @verbatim + * + * =================================================================== + * CDC Class Driver Description + * =================================================================== + * This driver manages the "Universal Serial Bus Class Definitions for Communications Devices + * Revision 1.2 November 16, 2007" and the sub-protocol specification of "Universal Serial Bus + * Communications Class Subclass Specification for PSTN Devices Revision 1.2 February 9, 2007" + * This driver implements the following aspects of the specification: + * - Device descriptor management + * - Configuration descriptor management + * - Enumeration as CDC device with 2 data endpoints (IN and OUT) and 1 command endpoint (IN) + * - Requests management (as described in section 6.2 in specification) + * - Abstract Control Model compliant + * - Union Functional collection (using 1 IN endpoint for control) + * - Data interface class + * + * These aspects may be enriched or modified for a specific user application. + * + * This driver doesn't implement the following aspects of the specification + * (but it is possible to manage these features with some modifications on this driver): + * - Any class-specific aspect relative to communication classes should be managed by user application. + * - All communication classes other than PSTN are not managed + * + * @endverbatim + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* BSPDependencies +- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" +- "stm32xxxxx_{eval}{discovery}_io.c" +EndBSPDependencies */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_cdc_acm.h" +#include "usbd_ctlreq.h" + +#define _CDC_IN_EP 0x81U /* EP1 for data IN */ +#define _CDC_OUT_EP 0x01U /* EP1 for data OUT */ +#define _CDC_CMD_EP 0x82U /* EP2 for CDC commands */ + +#define _CDC_CMD_ITF_NBR 0x00U /* Command Interface Number */ +#define _CDC_COM_ITF_NBR 0x01U /* Communication Interface Number */ + +#define _CDC_STR_DESC_IDX 0x00 + +uint8_t CDC_IN_EP[NUMBER_OF_CDC]; +uint8_t CDC_OUT_EP[NUMBER_OF_CDC]; +uint8_t CDC_CMD_EP[NUMBER_OF_CDC]; + +uint8_t CDC_CMD_ITF_NBR[NUMBER_OF_CDC]; +uint8_t CDC_COM_ITF_NBR[NUMBER_OF_CDC]; + +uint8_t CDC_STR_DESC_IDX[NUMBER_OF_CDC]; + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_CDC + * @brief usbd core module + * @{ + */ + +/** @defgroup USBD_CDC_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_CDC_Private_Defines + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_CDC_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_Private_FunctionPrototypes + * @{ + */ + +static uint8_t USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_CDC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum); +static uint8_t USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum); +static uint8_t USBD_CDC_EP0_RxReady(USBD_HandleTypeDef *pdev); + +static uint8_t *USBD_CDC_GetFSCfgDesc(uint16_t *length); +static uint8_t *USBD_CDC_GetHSCfgDesc(uint16_t *length); +static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc(uint16_t *length); +static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc(uint16_t *length); +static uint8_t *USBD_CDC_GetDeviceQualifierDescriptor(uint16_t *length); + +USBD_CDC_ACM_HandleTypeDef CDC_ACM_Class_Data[NUMBER_OF_CDC]; + +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_CDC_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_CDC_Private_Variables + * @{ + */ + +/* CDC interface class callbacks structure */ +USBD_ClassTypeDef USBD_CDC_ACM = + { + USBD_CDC_Init, + USBD_CDC_DeInit, + USBD_CDC_Setup, + NULL, /* EP0_TxSent, */ + USBD_CDC_EP0_RxReady, + USBD_CDC_DataIn, + USBD_CDC_DataOut, + NULL, + NULL, + NULL, + USBD_CDC_GetHSCfgDesc, + USBD_CDC_GetFSCfgDesc, + USBD_CDC_GetOtherSpeedCfgDesc, + USBD_CDC_GetDeviceQualifierDescriptor, +}; + +/* USB CDC device Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_CDC_CfgHSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = + { + /* Configuration Descriptor */ + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + LOBYTE(USB_CDC_CONFIG_DESC_SIZ), /* wTotalLength:no of returned bytes */ + HIBYTE(USB_CDC_CONFIG_DESC_SIZ), + (2 * NUMBER_OF_CDC), /* bNumInterfaces: 2 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ +#if (USBD_SELF_POWERED == 1U) + 0xC0, /* bmAttributes: Bus Powered according to user configuration */ +#else + 0x80, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* MaxPower 100 mA */ + + /******************** CDC0 block ********************/ + /******** IAD to associate the two CDC interfaces */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass */ + 0x02, /* bFunctionSubClass */ + 0x01, /* bFunctionProtocol */ + 0x00, /* iFunction (Index of string descriptor describing this function) */ + + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + _CDC_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + _CDC_STR_DESC_IDX, /* iInterface: */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /* Call Management Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + _CDC_COM_ITF_NBR, /* bDataInterface: 1 */ + + /* ACM Functional Descriptor */ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + _CDC_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* Endpoint 2 Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + CDC_HS_BINTERVAL, /* bInterval: */ + /*---------------------------------------------------------------------------*/ + + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + _CDC_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + +#if (NUMBER_OF_CDC > 1) + /******************** CDC1 block ********************/ + /******** IAD to associate the two CDC interfaces */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass */ + 0x02, /* bFunctionSubClass */ + 0x01, /* bFunctionProtocol */ + 0x00, /* iFunction (Index of string descriptor describing this function) */ + + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + _CDC_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + _CDC_STR_DESC_IDX, /* iInterface: */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /* Call Management Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + _CDC_COM_ITF_NBR, /* bDataInterface: 1 */ + + /* ACM Functional Descriptor */ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + _CDC_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* Endpoint 2 Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + CDC_HS_BINTERVAL, /* bInterval: */ + /*---------------------------------------------------------------------------*/ + + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + _CDC_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ +#endif + +#if (NUMBER_OF_CDC > 2) + /******************** CDC2 block ********************/ + /******** IAD to associate the two CDC interfaces */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass */ + 0x02, /* bFunctionSubClass */ + 0x01, /* bFunctionProtocol */ + 0x00, /* iFunction (Index of string descriptor describing this function) */ + + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + _CDC_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + _CDC_STR_DESC_IDX, /* iInterface: */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /* Call Management Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + _CDC_COM_ITF_NBR, /* bDataInterface: 1 */ + + /* ACM Functional Descriptor */ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + _CDC_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* Endpoint 2 Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + CDC_HS_BINTERVAL, /* bInterval: */ + /*---------------------------------------------------------------------------*/ + + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + _CDC_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ +#endif + +#if (NUMBER_OF_CDC > 3) + /******************** CDC3 block ********************/ + /******** IAD to associate the two CDC interfaces */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass */ + 0x02, /* bFunctionSubClass */ + 0x01, /* bFunctionProtocol */ + 0x00, /* iFunction (Index of string descriptor describing this function) */ + + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + _CDC_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + _CDC_STR_DESC_IDX, /* iInterface: */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /* Call Management Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + _CDC_COM_ITF_NBR, /* bDataInterface: 1 */ + + /* ACM Functional Descriptor */ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + _CDC_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* Endpoint 2 Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + CDC_HS_BINTERVAL, /* bInterval: */ + /*---------------------------------------------------------------------------*/ + + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + _CDC_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ +#endif + +#if (NUMBER_OF_CDC > 4) + /******************** CDC4 block ********************/ + /******** IAD to associate the two CDC interfaces */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass */ + 0x02, /* bFunctionSubClass */ + 0x01, /* bFunctionProtocol */ + 0x00, /* iFunction (Index of string descriptor describing this function) */ + + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + _CDC_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + _CDC_STR_DESC_IDX, /* iInterface: */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /* Call Management Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + _CDC_COM_ITF_NBR, /* bDataInterface: 1 */ + + /* ACM Functional Descriptor */ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + _CDC_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* Endpoint 2 Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + CDC_HS_BINTERVAL, /* bInterval: */ + /*---------------------------------------------------------------------------*/ + + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + _CDC_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ +#endif + +#if (NUMBER_OF_CDC > 5) + /******************** CDC5 block ********************/ + /******** IAD to associate the two CDC interfaces */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass */ + 0x02, /* bFunctionSubClass */ + 0x01, /* bFunctionProtocol */ + 0x00, /* iFunction (Index of string descriptor describing this function) */ + + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + _CDC_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + _CDC_STR_DESC_IDX, /* iInterface: */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /* Call Management Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + _CDC_COM_ITF_NBR, /* bDataInterface: 1 */ + + /* ACM Functional Descriptor */ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + _CDC_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* Endpoint 2 Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + CDC_HS_BINTERVAL, /* bInterval: */ + /*---------------------------------------------------------------------------*/ + + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + _CDC_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ +#endif + +#if (NUMBER_OF_CDC > 6) + /******************** CDC6 block ********************/ + /******** IAD to associate the two CDC interfaces */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass */ + 0x02, /* bFunctionSubClass */ + 0x01, /* bFunctionProtocol */ + 0x00, /* iFunction (Index of string descriptor describing this function) */ + + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + _CDC_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + _CDC_STR_DESC_IDX, /* iInterface: */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /* Call Management Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + _CDC_COM_ITF_NBR, /* bDataInterface: 1 */ + + /* ACM Functional Descriptor */ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + _CDC_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* Endpoint 2 Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + CDC_HS_BINTERVAL, /* bInterval: */ + /*---------------------------------------------------------------------------*/ + + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + _CDC_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ +#endif + +#if (NUMBER_OF_CDC > 7) + /******************** CDC7 block ********************/ + /******** IAD to associate the two CDC interfaces */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass */ + 0x02, /* bFunctionSubClass */ + 0x01, /* bFunctionProtocol */ + 0x00, /* iFunction (Index of string descriptor describing this function) */ + + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + _CDC_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + _CDC_STR_DESC_IDX, /* iInterface: */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /* Call Management Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + _CDC_COM_ITF_NBR, /* bDataInterface: 1 */ + + /* ACM Functional Descriptor */ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + _CDC_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* Endpoint 2 Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + CDC_HS_BINTERVAL, /* bInterval: */ + /*---------------------------------------------------------------------------*/ + + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + _CDC_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00 /* bInterval: ignore for Bulk transfer */ +#endif +}; + +/* USB CDC device Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_CDC_CfgFSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = + { + /* Configuration Descriptor */ + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + LOBYTE(USB_CDC_CONFIG_DESC_SIZ), /* wTotalLength:no of returned bytes */ + HIBYTE(USB_CDC_CONFIG_DESC_SIZ), + 0x02, /* bNumInterfaces: 2 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ +#if (USBD_SELF_POWERED == 1U) + 0xC0, /* bmAttributes: Bus Powered according to user configuration */ +#else + 0x80, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* MaxPower 100 mA */ + + /*---------------------------------------------------------------------------*/ + /******************** CDC0 block ********************/ + /******** IAD to associate the two CDC interfaces */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass */ + 0x02, /* bFunctionSubClass */ + 0x01, /* bFunctionProtocol */ + 0x00, /* iFunction (Index of string descriptor describing this function) */ + + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + /* Interface descriptor type */ + _CDC_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + _CDC_STR_DESC_IDX,/* iInterface: */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /* Call Management Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + _CDC_COM_ITF_NBR, /* bDataInterface: 1 */ + + /* ACM Functional Descriptor */ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + _CDC_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* Endpoint 2 Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + CDC_FS_BINTERVAL, /* bInterval: */ + /*---------------------------------------------------------------------------*/ + + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + _CDC_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + +#if (NUMBER_OF_CDC > 1) + /******************** CDC1 block ********************/ + /******** IAD to associate the two CDC interfaces */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass */ + 0x02, /* bFunctionSubClass */ + 0x01, /* bFunctionProtocol */ + 0x00, /* iFunction (Index of string descriptor describing this function) */ + + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + /* Interface descriptor type */ + _CDC_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + _CDC_STR_DESC_IDX,/* iInterface: */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /* Call Management Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + _CDC_COM_ITF_NBR, /* bDataInterface: 1 */ + + /* ACM Functional Descriptor */ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + _CDC_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* Endpoint 2 Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + CDC_FS_BINTERVAL, /* bInterval: */ + /*---------------------------------------------------------------------------*/ + + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + _CDC_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ +#endif + +#if (NUMBER_OF_CDC > 2) + /******************** CDC2 block ********************/ + /******** IAD to associate the two CDC interfaces */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass */ + 0x02, /* bFunctionSubClass */ + 0x01, /* bFunctionProtocol */ + 0x00, /* iFunction (Index of string descriptor describing this function) */ + + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + /* Interface descriptor type */ + _CDC_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + _CDC_STR_DESC_IDX,/* iInterface: */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /* Call Management Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + _CDC_COM_ITF_NBR, /* bDataInterface: 1 */ + + /* ACM Functional Descriptor */ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + _CDC_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* Endpoint 2 Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + CDC_FS_BINTERVAL, /* bInterval: */ + /*---------------------------------------------------------------------------*/ + + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + _CDC_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ +#endif + +#if (NUMBER_OF_CDC > 3) + /******************** CDC3 block ********************/ + /******** IAD to associate the two CDC interfaces */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass */ + 0x02, /* bFunctionSubClass */ + 0x01, /* bFunctionProtocol */ + 0x00, /* iFunction (Index of string descriptor describing this function) */ + + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + /* Interface descriptor type */ + _CDC_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + _CDC_STR_DESC_IDX,/* iInterface: */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /* Call Management Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + _CDC_COM_ITF_NBR, /* bDataInterface: 1 */ + + /* ACM Functional Descriptor */ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + _CDC_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* Endpoint 2 Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + CDC_FS_BINTERVAL, /* bInterval: */ + /*---------------------------------------------------------------------------*/ + + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + _CDC_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ +#endif + +#if (NUMBER_OF_CDC > 4) + /******************** CDC4 block ********************/ + /******** IAD to associate the two CDC interfaces */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass */ + 0x02, /* bFunctionSubClass */ + 0x01, /* bFunctionProtocol */ + 0x00, /* iFunction (Index of string descriptor describing this function) */ + + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + /* Interface descriptor type */ + _CDC_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + _CDC_STR_DESC_IDX,/* iInterface: */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /* Call Management Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + _CDC_COM_ITF_NBR, /* bDataInterface: 1 */ + + /* ACM Functional Descriptor */ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + _CDC_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* Endpoint 2 Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + CDC_FS_BINTERVAL, /* bInterval: */ + /*---------------------------------------------------------------------------*/ + + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + _CDC_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ +#endif + +#if (NUMBER_OF_CDC > 5) + /******************** CDC5 block ********************/ + /******** IAD to associate the two CDC interfaces */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass */ + 0x02, /* bFunctionSubClass */ + 0x01, /* bFunctionProtocol */ + 0x00, /* iFunction (Index of string descriptor describing this function) */ + + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + /* Interface descriptor type */ + _CDC_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + _CDC_STR_DESC_IDX,/* iInterface: */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /* Call Management Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + _CDC_COM_ITF_NBR, /* bDataInterface: 1 */ + + /* ACM Functional Descriptor */ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + _CDC_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* Endpoint 2 Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + CDC_FS_BINTERVAL, /* bInterval: */ + /*---------------------------------------------------------------------------*/ + + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + _CDC_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ +#endif + +#if (NUMBER_OF_CDC > 6) + /******************** CDC6 block ********************/ + /******** IAD to associate the two CDC interfaces */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass */ + 0x02, /* bFunctionSubClass */ + 0x01, /* bFunctionProtocol */ + 0x00, /* iFunction (Index of string descriptor describing this function) */ + + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + /* Interface descriptor type */ + _CDC_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + _CDC_STR_DESC_IDX,/* iInterface: */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /* Call Management Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + _CDC_COM_ITF_NBR, /* bDataInterface: 1 */ + + /* ACM Functional Descriptor */ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + _CDC_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* Endpoint 2 Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + CDC_FS_BINTERVAL, /* bInterval: */ + /*---------------------------------------------------------------------------*/ + + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + _CDC_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ +#endif + +#if (NUMBER_OF_CDC > 7) + /******************** CDC7 block ********************/ + /******** IAD to associate the two CDC interfaces */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass */ + 0x02, /* bFunctionSubClass */ + 0x01, /* bFunctionProtocol */ + 0x00, /* iFunction (Index of string descriptor describing this function) */ + + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + /* Interface descriptor type */ + _CDC_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + _CDC_STR_DESC_IDX,/* iInterface: */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /* Call Management Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + _CDC_COM_ITF_NBR, /* bDataInterface: 1 */ + + /* ACM Functional Descriptor */ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + _CDC_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* Endpoint 2 Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + CDC_FS_BINTERVAL, /* bInterval: */ + /*---------------------------------------------------------------------------*/ + + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + _CDC_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00 /* bInterval: ignore for Bulk transfer */ +#endif +}; + +/** + * @} + */ + +/** @defgroup USBD_CDC_Private_Functions + * @{ + */ + +/** + * @brief USBD_CDC_Init + * Initialize the CDC interface + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(cfgidx); + USBD_CDC_ACM_HandleTypeDef *hcdc = NULL; + + for (uint8_t i = 0; i < NUMBER_OF_CDC; i++) + { + hcdc = &CDC_ACM_Class_Data[i]; + + if (pdev->dev_speed == USBD_SPEED_HIGH) + { + /* Open EP IN */ + (void)USBD_LL_OpenEP(pdev, CDC_IN_EP[i], USBD_EP_TYPE_BULK, + CDC_DATA_HS_IN_PACKET_SIZE); + + pdev->ep_in[CDC_IN_EP[i] & 0xFU].is_used = 1U; + + /* Open EP OUT */ + (void)USBD_LL_OpenEP(pdev, CDC_OUT_EP[i], USBD_EP_TYPE_BULK, + CDC_DATA_HS_OUT_PACKET_SIZE); + + pdev->ep_out[CDC_OUT_EP[i] & 0xFU].is_used = 1U; + + /* Set bInterval for CDC CMD Endpoint */ + pdev->ep_in[CDC_CMD_EP[i] & 0xFU].bInterval = CDC_HS_BINTERVAL; + } + else + { + /* Open EP IN */ + (void)USBD_LL_OpenEP(pdev, CDC_IN_EP[i], USBD_EP_TYPE_BULK, + CDC_DATA_FS_IN_PACKET_SIZE); + + pdev->ep_in[CDC_IN_EP[i] & 0xFU].is_used = 1U; + + /* Open EP OUT */ + (void)USBD_LL_OpenEP(pdev, CDC_OUT_EP[i], USBD_EP_TYPE_BULK, + CDC_DATA_FS_OUT_PACKET_SIZE); + + pdev->ep_out[CDC_OUT_EP[i] & 0xFU].is_used = 1U; + + /* Set bInterval for CMD Endpoint */ + pdev->ep_in[CDC_CMD_EP[i] & 0xFU].bInterval = CDC_FS_BINTERVAL; + } + + /* Open Command IN EP */ + (void)USBD_LL_OpenEP(pdev, CDC_CMD_EP[i], USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE); + pdev->ep_in[CDC_CMD_EP[i] & 0xFU].is_used = 1U; + + /* Init physical Interface components */ + ((USBD_CDC_ACM_ItfTypeDef *)pdev->pUserData_CDC_ACM)->Init(i); + + /* Init Xfer states */ + hcdc->TxState = 0U; + hcdc->RxState = 0U; + + if (pdev->dev_speed == USBD_SPEED_HIGH) + { + /* Prepare Out endpoint to receive next packet */ + (void)USBD_LL_PrepareReceive(pdev, CDC_OUT_EP[i], hcdc->RxBuffer, + CDC_DATA_HS_OUT_PACKET_SIZE); + } + else + { + /* Prepare Out endpoint to receive next packet */ + (void)USBD_LL_PrepareReceive(pdev, CDC_OUT_EP[i], hcdc->RxBuffer, + CDC_DATA_FS_OUT_PACKET_SIZE); + } + } + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_Init + * DeInitialize the CDC layer + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_CDC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(cfgidx); + for (uint8_t i = 0; i < NUMBER_OF_CDC; i++) + { + /* Close EP IN */ + (void)USBD_LL_CloseEP(pdev, CDC_IN_EP[i]); + pdev->ep_in[CDC_IN_EP[i] & 0xFU].is_used = 0U; + + /* Close EP OUT */ + (void)USBD_LL_CloseEP(pdev, CDC_OUT_EP[i]); + pdev->ep_out[CDC_OUT_EP[i] & 0xFU].is_used = 0U; + + /* Close Command IN EP */ + (void)USBD_LL_CloseEP(pdev, CDC_CMD_EP[i]); + pdev->ep_in[CDC_CMD_EP[i] & 0xFU].is_used = 0U; + pdev->ep_in[CDC_CMD_EP[i] & 0xFU].bInterval = 0U; + + /* DeInit physical Interface components */ + ((USBD_CDC_ACM_ItfTypeDef *)pdev->pUserData_CDC_ACM)->DeInit(i); + } + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_Setup + * Handle the CDC specific requests + * @param pdev: instance + * @param req: usb requests + * @retval status + */ +static uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev, + USBD_SetupReqTypedef *req) +{ + USBD_CDC_ACM_HandleTypeDef *hcdc = NULL; + uint16_t len; + uint8_t ifalt = 0U; + uint16_t status_info = 0U; + USBD_StatusTypeDef ret = USBD_OK; + + uint8_t windex_to_ch = 0; + + for (uint8_t i = 0; i < NUMBER_OF_CDC; i++) + { + if (LOBYTE(req->wIndex) == CDC_CMD_ITF_NBR[i] || LOBYTE(req->wIndex) == CDC_COM_ITF_NBR[i]) + { + windex_to_ch = i; + break; + } + } + + hcdc = &CDC_ACM_Class_Data[windex_to_ch]; + + switch (req->bmRequest & USB_REQ_TYPE_MASK) + { + case USB_REQ_TYPE_CLASS: + if (req->wLength != 0U) + { + if ((req->bmRequest & 0x80U) != 0U) + { + ((USBD_CDC_ACM_ItfTypeDef *)pdev->pUserData_CDC_ACM)->Control(windex_to_ch, req->bRequest, (uint8_t *)hcdc->data[windex_to_ch], req->wLength); + + len = MIN(CDC_REQ_MAX_DATA_SIZE, req->wLength); + (void)USBD_CtlSendData(pdev, (uint8_t *)hcdc->data[windex_to_ch], len); + } + else + { + hcdc->CmdOpCode = req->bRequest; + hcdc->CmdLength = (uint8_t)req->wLength; + + (void)USBD_CtlPrepareRx(pdev, (uint8_t *)hcdc->data[windex_to_ch], req->wLength); + } + } + else + { + ((USBD_CDC_ACM_ItfTypeDef *)pdev->pUserData_CDC_ACM)->Control(windex_to_ch, req->bRequest, (uint8_t *)req, 0U); + } + break; + + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) + { + case USB_REQ_GET_STATUS: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_GET_INTERFACE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, &ifalt, 1U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_SET_INTERFACE: + if (pdev->dev_state != USBD_STATE_CONFIGURED) + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_CLEAR_FEATURE: + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + + return (uint8_t)ret; +} + +/** + * @brief USBD_CDC_DataIn + * Data sent on non-control IN endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + USBD_CDC_ACM_HandleTypeDef *hcdc = NULL; + PCD_HandleTypeDef *hpcd = pdev->pData; + uint8_t ep_to_ch = 0; + + for (uint8_t i = 0; i < NUMBER_OF_CDC; i++) + { + if (epnum == (CDC_IN_EP[i] & 0x0F)) + { + ep_to_ch = i; + break; + } + } + + hcdc = &CDC_ACM_Class_Data[ep_to_ch]; + + if ((pdev->ep_in[epnum].total_length > 0U) && + ((pdev->ep_in[epnum].total_length % hpcd->IN_ep[epnum].maxpacket) == 0U)) + { + /* Update the packet total length */ + pdev->ep_in[epnum].total_length = 0U; + + /* Send ZLP */ + (void)USBD_LL_Transmit(pdev, epnum, NULL, 0U); + } + else + { + hcdc->TxState = 0U; + + if (((USBD_CDC_ACM_ItfTypeDef *)pdev->pUserData_CDC_ACM)->TransmitCplt != NULL) + { + ((USBD_CDC_ACM_ItfTypeDef *)pdev->pUserData_CDC_ACM)->TransmitCplt(ep_to_ch, hcdc->TxBuffer, &hcdc->TxLength, epnum); + } + } + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_DataOut + * Data received on non-control Out endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +static uint8_t USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + USBD_CDC_ACM_HandleTypeDef *hcdc = NULL; + uint8_t ep_to_ch = 0; + + for (uint8_t i = 0; i < NUMBER_OF_CDC; i++) + { + if (epnum == CDC_OUT_EP[i]) + { + ep_to_ch = i; + break; + } + } + + hcdc = &CDC_ACM_Class_Data[ep_to_ch]; + + /* Get the received data length */ + hcdc->RxLength = USBD_LL_GetRxDataSize(pdev, epnum); + + /* USB data will be immediately processed, this allow next USB traffic being + NAKed till the end of the application Xfer */ + + ((USBD_CDC_ACM_ItfTypeDef *)pdev->pUserData_CDC_ACM)->Receive(ep_to_ch, hcdc->RxBuffer, &hcdc->RxLength); + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_EP0_RxReady + * Handle EP0 Rx Ready event + * @param pdev: device instance + * @retval status + */ +static uint8_t USBD_CDC_EP0_RxReady(USBD_HandleTypeDef *pdev) +{ + USBD_CDC_ACM_HandleTypeDef *hcdc = NULL; + + for (uint8_t i = 0; i < NUMBER_OF_CDC; i++) + { + hcdc = &CDC_ACM_Class_Data[i]; + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + if ((pdev->pUserData_CDC_ACM != NULL) && (hcdc->CmdOpCode != 0xFFU)) + { + ((USBD_CDC_ACM_ItfTypeDef *)pdev->pUserData_CDC_ACM)->Control(i, hcdc->CmdOpCode, (uint8_t *)hcdc->data[i], (uint16_t)hcdc->CmdLength); + hcdc->CmdOpCode = 0xFFU; + } + } + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_GetFSCfgDesc + * Return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CDC_GetFSCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_CDC_CfgFSDesc); + + return USBD_CDC_CfgFSDesc; +} + +/** + * @brief USBD_CDC_GetHSCfgDesc + * Return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CDC_GetHSCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_CDC_CfgHSDesc); + + return USBD_CDC_CfgHSDesc; +} + +/** + * @brief USBD_CDC_GetOtherSpeedCfgDesc + * Return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_CDC_CfgFSDesc); + + return USBD_CDC_CfgFSDesc; +} + +/** + * @brief USBD_CDC_GetDeviceQualifierDescriptor + * return Device Qualifier descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +uint8_t *USBD_CDC_GetDeviceQualifierDescriptor(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_CDC_DeviceQualifierDesc); + + return USBD_CDC_DeviceQualifierDesc; +} + +/** + * @brief USBD_CDC_RegisterInterface + * @param pdev: device instance + * @param fops: CD Interface callback + * @retval status + */ +uint8_t USBD_CDC_ACM_RegisterInterface(USBD_HandleTypeDef *pdev, + USBD_CDC_ACM_ItfTypeDef *fops) +{ + if (fops == NULL) + { + return (uint8_t)USBD_FAIL; + } + + pdev->pUserData_CDC_ACM = fops; + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_SetTxBuffer + * @param pdev: device instance + * @param pbuff: Tx Buffer + * @retval status + */ +uint8_t USBD_CDC_SetTxBuffer(uint8_t ch, USBD_HandleTypeDef *pdev, + uint8_t *pbuff, uint32_t length) +{ + USBD_CDC_ACM_HandleTypeDef *hcdc = NULL; + + hcdc = &CDC_ACM_Class_Data[ch]; + + hcdc->TxBuffer = pbuff; + hcdc->TxLength = length; + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_SetRxBuffer + * @param pdev: device instance + * @param pbuff: Rx Buffer + * @retval status + */ +uint8_t USBD_CDC_SetRxBuffer(uint8_t ch, USBD_HandleTypeDef *pdev, uint8_t *pbuff) +{ + USBD_CDC_ACM_HandleTypeDef *hcdc = NULL; + + hcdc = &CDC_ACM_Class_Data[ch]; + + hcdc->RxBuffer = pbuff; + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_TransmitPacket + * Transmit packet on IN endpoint + * @param pdev: device instance + * @retval status + */ +uint8_t USBD_CDC_TransmitPacket(uint8_t ch, USBD_HandleTypeDef *pdev) +{ + USBD_CDC_ACM_HandleTypeDef *hcdc = NULL; + USBD_StatusTypeDef ret = USBD_BUSY; + + hcdc = &CDC_ACM_Class_Data[ch]; + + if (hcdc->TxState == 0U) + { + /* Tx Transfer in progress */ + hcdc->TxState = 1U; + + /* Update the packet total length */ + pdev->ep_in[CDC_IN_EP[ch] & 0xFU].total_length = hcdc->TxLength; + + /* Transmit next packet */ + (void)USBD_LL_Transmit(pdev, CDC_IN_EP[ch], hcdc->TxBuffer, hcdc->TxLength); + + ret = USBD_OK; + } + + return (uint8_t)ret; +} + +/** + * @brief USBD_CDC_ACM_ReceivePacket + * prepare OUT Endpoint for reception + * @param pdev: device instance + * @retval status + */ +uint8_t USBD_CDC_ReceivePacket(uint8_t ch, USBD_HandleTypeDef *pdev) +{ + USBD_CDC_ACM_HandleTypeDef *hcdc = NULL; + + hcdc = &CDC_ACM_Class_Data[ch]; + + if (pdev->dev_speed == USBD_SPEED_HIGH) + { + /* Prepare Out endpoint to receive next packet */ + (void)USBD_LL_PrepareReceive(pdev, CDC_OUT_EP[ch], hcdc->RxBuffer, + CDC_DATA_HS_OUT_PACKET_SIZE); + } + else + { + /* Prepare Out endpoint to receive next packet */ + (void)USBD_LL_PrepareReceive(pdev, CDC_OUT_EP[ch], hcdc->RxBuffer, + CDC_DATA_FS_OUT_PACKET_SIZE); + } + + return (uint8_t)USBD_OK; +} + +void USBD_Update_CDC_ACM_DESC(uint8_t *desc, + uint8_t cmd_itf, + uint8_t com_itf, + uint8_t in_ep, + uint8_t cmd_ep, + uint8_t out_ep, + uint8_t str_idx) +{ + desc += 9; + for (uint8_t i = 0; i < NUMBER_OF_CDC; i++) + { + desc[2] = cmd_itf; + desc[16] = str_idx; + desc[10] = cmd_itf; + desc[26] = com_itf; + desc[34] = cmd_itf; + desc[35] = com_itf; + desc[38] = cmd_ep; + desc[45] = com_itf; + desc[54] = out_ep; + desc[61] = in_ep; + + desc += 66; + CDC_IN_EP[i] = in_ep; + CDC_OUT_EP[i] = out_ep; + CDC_CMD_EP[i] = cmd_ep; + CDC_CMD_ITF_NBR[i] = cmd_itf; + CDC_COM_ITF_NBR[i] = com_itf; + CDC_STR_DESC_IDX[i] = str_idx; + + in_ep += 2; + cmd_ep = in_ep + 1; + out_ep++; + str_idx++; + + cmd_itf += 2; + com_itf = cmd_itf + 1; + } +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/CDC_ECM/Inc/usbd_cdc_ecm.h b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/CDC_ECM/Inc/usbd_cdc_ecm.h new file mode 100644 index 0000000..a602326 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/CDC_ECM/Inc/usbd_cdc_ecm.h @@ -0,0 +1,262 @@ +/** + ****************************************************************************** + * @file usbd_cdc_ecm.h + * @author MCD Application Team + * @brief header file for the usbd_cdc_ecm.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_CDC_ECM_H +#define __USB_CDC_ECM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ioreq.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup usbd_cdc_ecm + * @brief This file is the Header file for usbd_cdc_ecm.c + * @{ + */ + + +/** @defgroup usbd_cdc_ecm_Exported_Defines + * @{ + */ + +#define CDC_ECM_STR_DESC "STM32 CDC ECM" + +/* Comment this define in order to disable the CDC ECM Notification pipe */ + +#ifndef CDC_ECM_HS_BINTERVAL +#define CDC_ECM_HS_BINTERVAL 0x10U +#endif /* CDC_ECM_HS_BINTERVAL */ + +#ifndef CDC_ECM_FS_BINTERVAL +#define CDC_ECM_FS_BINTERVAL 0x10U +#endif /* CDC_ECM_FS_BINTERVAL */ + +#ifndef USBD_SUPPORT_USER_STRING_DESC +#define USBD_SUPPORT_USER_STRING_DESC 1U +#endif /* USBD_SUPPORT_USER_STRING_DESC */ + +/* CDC_ECM Endpoints parameters: you can fine tune these values depending on the needed baudrates and performance. */ +#define CDC_ECM_DATA_HS_MAX_PACKET_SIZE 512U /* Endpoint IN & OUT Packet size */ +#define CDC_ECM_DATA_FS_MAX_PACKET_SIZE 64U /* Endpoint IN & OUT Packet size */ +#define CDC_ECM_CMD_PACKET_SIZE 16U /* Control Endpoint Packet size */ + +#define CDC_ECM_CONFIG_DESC_SIZE 79U + +#define CDC_ECM_DATA_BUFFER_SIZE 2000U + +#define CDC_ECM_DATA_HS_IN_PACKET_SIZE CDC_ECM_DATA_HS_MAX_PACKET_SIZE +#define CDC_ECM_DATA_HS_OUT_PACKET_SIZE CDC_ECM_DATA_HS_MAX_PACKET_SIZE + +#define CDC_ECM_DATA_FS_IN_PACKET_SIZE CDC_ECM_DATA_FS_MAX_PACKET_SIZE +#define CDC_ECM_DATA_FS_OUT_PACKET_SIZE CDC_ECM_DATA_FS_MAX_PACKET_SIZE + +/*---------------------------------------------------------------------*/ +/* CDC_ECM definitions */ +/*---------------------------------------------------------------------*/ +#define CDC_ECM_SEND_ENCAPSULATED_COMMAND 0x00U +#define CDC_ECM_GET_ENCAPSULATED_RESPONSE 0x01U +#define CDC_ECM_SET_ETH_MULTICAST_FILTERS 0x40U +#define CDC_ECM_SET_ETH_PWRM_PATTERN_FILTER 0x41U +#define CDC_ECM_GET_ETH_PWRM_PATTERN_FILTER 0x42U +#define CDC_ECM_SET_ETH_PACKET_FILTER 0x43U +#define CDC_ECM_GET_ETH_STATISTIC 0x44U + +#define CDC_ECM_NET_DISCONNECTED 0x00U +#define CDC_ECM_NET_CONNECTED 0x01U + + +/* Ethernet statistics definitions */ +#define CDC_ECM_XMIT_OK_VAL CDC_ECM_ETH_STATS_VAL_ENABLED +#define CDC_ECM_XMIT_OK 0x01U +#define CDC_ECM_RVC_OK 0x02U +#define CDC_ECM_XMIT_ERROR 0x04U +#define CDC_ECM_RCV_ERROR 0x08U +#define CDC_ECM_RCV_NO_BUFFER 0x10U +#define CDC_ECM_DIRECTED_BYTES_XMIT 0x20U +#define CDC_ECM_DIRECTED_FRAMES_XMIT 0x40U +#define CDC_ECM_MULTICAST_BYTES_XMIT 0x80U + +#define CDC_ECM_MULTICAST_FRAMES_XMIT 0x01U +#define CDC_ECM_BROADCAST_BYTES_XMIT 0x02U +#define CDC_ECM_BROADCAST_FRAMES_XMIT 0x04U +#define CDC_ECM_DIRECTED_BYTES_RCV 0x08U +#define CDC_ECM_DIRECTED_FRAMES_RCV 0x10U +#define CDC_ECM_MULTICAST_BYTES_RCV 0x20U +#define CDC_ECM_MULTICAST_FRAMES_RCV 0x40U +#define CDC_ECM_BROADCAST_BYTES_RCV 0x80U + +#define CDC_ECM_BROADCAST_FRAMES_RCV 0x01U +#define CDC_ECM_RCV_CRC_ERROR 0x02U +#define CDC_ECM_TRANSMIT_QUEUE_LENGTH 0x04U +#define CDC_ECM_RCV_ERROR_ALIGNMENT 0x08U +#define CDC_ECM_XMIT_ONE_COLLISION 0x10U +#define CDC_ECM_XMIT_MORE_COLLISIONS 0x20U +#define CDC_ECM_XMIT_DEFERRED 0x40U +#define CDC_ECM_XMIT_MAX_COLLISIONS 0x80U + +#define CDC_ECM_RCV_OVERRUN 0x40U +#define CDC_ECM_XMIT_UNDERRUN 0x40U +#define CDC_ECM_XMIT_HEARTBEAT_FAILURE 0x40U +#define CDC_ECM_XMIT_TIMES_CRS_LOST 0x40U +#define CDC_ECM_XMIT_LATE_COLLISIONS 0x40U + +#define CDC_ECM_ETH_STATS_RESERVED 0xE0U +#define CDC_ECM_BMREQUEST_TYPE_ECM 0xA1U + +/* MAC String index */ +#define CDC_ECM_MAC_STRING_INDEX 6U + +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +typedef struct +{ + int8_t (*Init)(void); + int8_t (*DeInit)(void); + int8_t (*Control)(uint8_t cmd, uint8_t *pbuf, uint16_t length); + int8_t (*Receive)(uint8_t *Buf, uint32_t *Len); + int8_t (*TransmitCplt)(uint8_t *Buf, uint32_t *Len, uint8_t epnum); + int8_t (*Process)(USBD_HandleTypeDef *pdev); + const uint8_t *pStrDesc; +} USBD_CDC_ECM_ItfTypeDef; + +typedef struct +{ + uint8_t bmRequest; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; + uint8_t data[8]; +} USBD_CDC_ECM_NotifTypeDef; + +typedef struct +{ + uint32_t data[CDC_ECM_DATA_BUFFER_SIZE / 4U]; /* Force 32-bit alignment */ + uint8_t CmdOpCode; + uint8_t CmdLength; + uint8_t Reserved1; /* Reserved Byte to force 4 bytes alignment of following fields */ + uint8_t Reserved2; /* Reserved Byte to force 4 bytes alignment of following fields */ + uint8_t *RxBuffer; + uint8_t *TxBuffer; + uint32_t RxLength; + uint32_t TxLength; + + __IO uint32_t TxState; + __IO uint32_t RxState; + + __IO uint32_t MaxPcktLen; + __IO uint32_t LinkStatus; + __IO uint32_t NotificationStatus; + USBD_CDC_ECM_NotifTypeDef Req; +} USBD_CDC_ECM_HandleTypeDef; + +typedef enum +{ + ECM_NETWORK_CONNECTION = 0x00, + ECM_RESPONSE_AVAILABLE = 0x01, + ECM_CONNECTION_SPEED_CHANGE = 0x2A +} USBD_CDC_ECM_NotifCodeTypeDef; + +/** @defgroup USBD_CORE_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_Variables + * @{ + */ + +extern USBD_ClassTypeDef USBD_CDC_ECM; + +extern uint8_t CDC_ECM_IN_EP; +extern uint8_t CDC_ECM_OUT_EP; +extern uint8_t CDC_ECM_CMD_EP; +extern uint8_t CDC_ECM_CMD_ITF_NBR; +extern uint8_t CDC_ECM_COM_ITF_NBR; +extern uint8_t CDC_ECM_STR_DESC_IDX; + +/** + * @} + */ + +/** @defgroup USB_CORE_Exported_Functions + * @{ + */ +uint8_t USBD_CDC_ECM_RegisterInterface(USBD_HandleTypeDef *pdev, + USBD_CDC_ECM_ItfTypeDef *fops); + +uint8_t USBD_CDC_ECM_SetTxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff, + uint32_t length); + +uint8_t USBD_CDC_ECM_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff); + +uint8_t USBD_CDC_ECM_ReceivePacket(USBD_HandleTypeDef *pdev); + +uint8_t USBD_CDC_ECM_TransmitPacket(USBD_HandleTypeDef *pdev); + +uint8_t USBD_CDC_ECM_SendNotification(USBD_HandleTypeDef *pdev, + USBD_CDC_ECM_NotifCodeTypeDef Notif, + uint16_t bVal, uint8_t *pData); + +void USBD_Update_CDC_ECM_DESC(uint8_t *desc, + uint8_t cmd_itf, + uint8_t com_itf, + uint8_t in_ep, + uint8_t cmd_ep, + uint8_t out_ep, + uint8_t str_idx); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_CDC_ECM_H */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/CDC_ECM/Src/usbd_cdc_ecm.c b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/CDC_ECM/Src/usbd_cdc_ecm.c new file mode 100644 index 0000000..9d5ab5f --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/CDC_ECM/Src/usbd_cdc_ecm.c @@ -0,0 +1,1160 @@ +/** + ****************************************************************************** + * @file usbd_cdc_ecm.c + * @author MCD Application Team + * @brief This file provides the high layer firmware functions to manage the + * following functionalities of the USB CDC_ECM Class: + * - Initialization and Configuration of high and low layer + * - Enumeration as CDC_ECM Device (and enumeration for each implemented memory interface) + * - OUT/IN data transfer + * - Command IN transfer (class requests management) + * - Error management + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* BSPDependencies +- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" +- "stm32xxxxx_{eval}{discovery}_io.c" +EndBSPDependencies */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_cdc_ecm.h" +#include "usbd_ctlreq.h" + +#include "usbd_cdc_ecm_if.h" + +#define _CDC_ECM_IN_EP 0x81U /* EP1 for data IN */ +#define _CDC_ECM_OUT_EP 0x01U /* EP1 for data OUT */ +#define _CDC_ECM_CMD_EP 0x82U /* EP2 for CDC ECM commands */ +#define _CDC_ECM_CMD_ITF_NBR 0x00U /* Command Interface Number 0 */ +#define _CDC_ECM_COM_ITF_NBR 0x01U /* Communication Interface Number 0 */ +#define _CDC_ECM_STR_DESC_IDX 0x00U + +uint8_t CDC_ECM_IN_EP = _CDC_ECM_IN_EP; +uint8_t CDC_ECM_OUT_EP = _CDC_ECM_OUT_EP; +uint8_t CDC_ECM_CMD_EP = _CDC_ECM_CMD_EP; +uint8_t CDC_ECM_CMD_ITF_NBR = _CDC_ECM_CMD_ITF_NBR; +uint8_t CDC_ECM_COM_ITF_NBR = _CDC_ECM_COM_ITF_NBR; +uint8_t CDC_ECM_STR_DESC_IDX = _CDC_ECM_STR_DESC_IDX; + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_CDC_ECM + * @brief usbd core module + * @{ + */ + +/** @defgroup USBD_CDC_ECM_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_ECM_Private_Defines + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_CDC_ECM_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_ECM_Private_FunctionPrototypes + * @{ + */ + +static uint8_t USBD_CDC_ECM_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_CDC_ECM_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_CDC_ECM_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum); +static uint8_t USBD_CDC_ECM_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum); +static uint8_t USBD_CDC_ECM_EP0_RxReady(USBD_HandleTypeDef *pdev); +static uint8_t USBD_CDC_ECM_Setup(USBD_HandleTypeDef *pdev, + USBD_SetupReqTypedef *req); + +static uint8_t *USBD_CDC_ECM_GetFSCfgDesc(uint16_t *length); +static uint8_t *USBD_CDC_ECM_GetHSCfgDesc(uint16_t *length); +static uint8_t *USBD_CDC_ECM_GetOtherSpeedCfgDesc(uint16_t *length); + +#if (USBD_SUPPORT_USER_STRING_DESC == 1U) +static uint8_t *USBD_CDC_ECM_USRStringDescriptor(USBD_HandleTypeDef *pdev, + uint8_t index, uint16_t *length); +#endif + +uint8_t *USBD_CDC_ECM_GetDeviceQualifierDescriptor(uint16_t *length); + +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_CDC_ECM_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, +}; + +static uint32_t ConnSpeedTab[2] = {CDC_ECM_CONNECT_SPEED_UPSTREAM, + CDC_ECM_CONNECT_SPEED_DOWNSTREAM}; + +/** + * @} + */ + +/** @defgroup USBD_CDC_ECM_Private_Variables + * @{ + */ + +static USBD_CDC_ECM_HandleTypeDef CDC_ECM_Instance; + +/* CDC_ECM interface class callbacks structure */ +USBD_ClassTypeDef USBD_CDC_ECM = + { + USBD_CDC_ECM_Init, + USBD_CDC_ECM_DeInit, + USBD_CDC_ECM_Setup, + NULL, /* EP0_TxSent, */ + USBD_CDC_ECM_EP0_RxReady, + USBD_CDC_ECM_DataIn, + USBD_CDC_ECM_DataOut, + NULL, + NULL, + NULL, + USBD_CDC_ECM_GetHSCfgDesc, + USBD_CDC_ECM_GetFSCfgDesc, + USBD_CDC_ECM_GetOtherSpeedCfgDesc, + USBD_CDC_ECM_GetDeviceQualifierDescriptor, +#if (USBD_SUPPORT_USER_STRING_DESC == 1U) + USBD_CDC_ECM_USRStringDescriptor, +#endif +}; + +/* USB CDC_ECM device Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_CDC_ECM_CfgHSDesc[CDC_ECM_CONFIG_DESC_SIZE] __ALIGN_END = + { + /* Configuration Descriptor */ + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + LOBYTE(CDC_ECM_CONFIG_DESC_SIZE), /* wTotalLength:no of returned bytes */ + HIBYTE(CDC_ECM_CONFIG_DESC_SIZE), + 0x02, /* bNumInterfaces: 2 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ +#if (USBD_SELF_POWERED == 1U) + 0xC0, /* bmAttributes: Bus Powered according to user configuration */ +#else + 0x80, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* MaxPower (mA) */ + + /*---------------------------------------------------------------------------*/ + + /* IAD descriptor */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_ECM_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass (Wireless Controller) */ + 0x06, /* bFunctionSubClass */ + 0x00, /* bFunctionProtocol */ + _CDC_ECM_STR_DESC_IDX, /* iFunction */ + + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ + _CDC_ECM_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoint used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x06, /* bInterfaceSubClass: Ethernet Control Model */ + 0x00, /* bInterfaceProtocol: No specific protocol required */ + 0x00, /* iInterface */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header functional descriptor */ + 0x10, /* bcd CDC_ECM: spec release number: 1.10 */ + 0x01, + + /* CDC_ECM Functional Descriptor */ + 0x0D, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x0F, /* Ethernet Networking functional descriptor subtype */ + CDC_ECM_MAC_STRING_INDEX, /* Device's MAC string index */ + CDC_ECM_ETH_STATS_BYTE3, /* Ethernet statistics byte 3 (bitmap) */ + CDC_ECM_ETH_STATS_BYTE2, /* Ethernet statistics byte 2 (bitmap) */ + CDC_ECM_ETH_STATS_BYTE1, /* Ethernet statistics byte 1 (bitmap) */ + CDC_ECM_ETH_STATS_BYTE0, /* Ethernet statistics byte 0 (bitmap) */ + LOBYTE(CDC_ECM_ETH_MAX_SEGSZE), + HIBYTE(CDC_ECM_ETH_MAX_SEGSZE), /* wMaxSegmentSize: Ethernet Maximum Segment size, typically 1514 bytes */ + LOBYTE(CDC_ECM_ETH_NBR_MACFILTERS), + HIBYTE(CDC_ECM_ETH_NBR_MACFILTERS), /* wNumberMCFilters: the number of multicast filters */ + CDC_ECM_ETH_NBR_PWRFILTERS, /* bNumberPowerFilters: the number of wakeup power filters */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union functional descriptor */ + _CDC_ECM_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_ECM_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* Communication Endpoint Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_ECM_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_ECM_CMD_PACKET_SIZE), /* wMaxPacketSize */ + HIBYTE(CDC_ECM_CMD_PACKET_SIZE), + CDC_ECM_HS_BINTERVAL, /* bInterval */ + + /*----------------------*/ + + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + _CDC_ECM_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass */ + 0x00, /* bInterfaceProtocol */ + 0x00, /* iInterface */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_ECM_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_ECM_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize */ + HIBYTE(CDC_ECM_DATA_HS_MAX_PACKET_SIZE), + 0xFF, /* bInterval: ignore for Bulk transfer */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_ECM_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_ECM_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize */ + HIBYTE(CDC_ECM_DATA_HS_MAX_PACKET_SIZE), + 0xFF /* bInterval: ignore for Bulk transfer */ +}; + +/* USB CDC_ECM device Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_CDC_ECM_CfgFSDesc[CDC_ECM_CONFIG_DESC_SIZE] __ALIGN_END = + { + /* Configuration Descriptor */ + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + LOBYTE(CDC_ECM_CONFIG_DESC_SIZE), /* wTotalLength: Total size of the Config descriptor */ + HIBYTE(CDC_ECM_CONFIG_DESC_SIZE), + 0x02, /* bNumInterfaces: 2 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ +#if (USBD_SELF_POWERED == 1U) + 0xC0, /* bmAttributes: Bus Powered according to user configuration */ +#else + 0x80, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* MaxPower (mA) */ + + /*---------------------------------------------------------------------------*/ + /* IAD descriptor */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_ECM_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass (Wireless Controller) */ + 0x06, /* bFunctionSubClass */ + 0x00, /* bFunctionProtocol */ + _CDC_ECM_STR_DESC_IDX, /* iFunction */ + + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ + _CDC_ECM_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoint used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x06, /* bInterfaceSubClass: Ethernet Control Model */ + 0x00, /* bInterfaceProtocol: No specific protocol required */ + 0x00, /* iInterface */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header functional descriptor */ + 0x10, /* bcd CDC_ECM : spec release number: 1.20 */ + 0x01, + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union functional descriptor */ + _CDC_ECM_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_ECM_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* CDC_ECM Functional Descriptor */ + 0x0D, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x0F, /* Ethernet Networking functional descriptor subtype */ + CDC_ECM_MAC_STRING_INDEX, /* Device's MAC string index */ + CDC_ECM_ETH_STATS_BYTE3, /* Ethernet statistics byte 3 (bitmap) */ + CDC_ECM_ETH_STATS_BYTE2, /* Ethernet statistics byte 2 (bitmap) */ + CDC_ECM_ETH_STATS_BYTE1, /* Ethernet statistics byte 1 (bitmap) */ + CDC_ECM_ETH_STATS_BYTE0, /* Ethernet statistics byte 0 (bitmap) */ + LOBYTE(CDC_ECM_ETH_MAX_SEGSZE), + HIBYTE(CDC_ECM_ETH_MAX_SEGSZE), /* wMaxSegmentSize: Ethernet Maximum Segment size, typically 1514 bytes */ + LOBYTE(CDC_ECM_ETH_NBR_MACFILTERS), + HIBYTE(CDC_ECM_ETH_NBR_MACFILTERS), /* wNumberMCFilters: the number of multicast filters */ + CDC_ECM_ETH_NBR_PWRFILTERS, /* bNumberPowerFilters: the number of wakeup power filters */ + + /* Communication Endpoint Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_ECM_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_ECM_CMD_PACKET_SIZE), /* wMaxPacketSize */ + HIBYTE(CDC_ECM_CMD_PACKET_SIZE), + CDC_ECM_FS_BINTERVAL, /* bInterval */ + + /*----------------------*/ + + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + _CDC_ECM_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC_ECM */ + 0x00, /* bInterfaceSubClass */ + 0x00, /* bInterfaceProtocol */ + 0x00, /* iInterface */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_ECM_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_ECM_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize */ + HIBYTE(CDC_ECM_DATA_FS_MAX_PACKET_SIZE), + 0xFF, /* bInterval: ignore for Bulk transfer */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_ECM_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_ECM_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize */ + HIBYTE(CDC_ECM_DATA_FS_MAX_PACKET_SIZE), + 0xFF /* bInterval: ignore for Bulk transfer */ +}; + +__ALIGN_BEGIN static uint8_t USBD_CDC_ECM_OtherSpeedCfgDesc[CDC_ECM_CONFIG_DESC_SIZE] __ALIGN_END = + { + /* Configuration Descriptor */ + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + LOBYTE(CDC_ECM_CONFIG_DESC_SIZE), /* wTotalLength */ + HIBYTE(CDC_ECM_CONFIG_DESC_SIZE), + 0x02, /* bNumInterfaces: 2 interfaces */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x04, /* iConfiguration: Index of string descriptor describing the configuration */ +#if (USBD_SELF_POWERED == 1U) + 0xC0, /* bmAttributes: Bus Powered according to user configuration */ +#else + 0x80, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* MaxPower (mA) */ + + /*--------------------------------------- ------------------------------------*/ + /* IAD descriptor */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_ECM_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0x02, /* bFunctionClass (Wireless Controller) */ + 0x06, /* bFunctionSubClass */ + 0x00, /* bFunctionProtocol */ + _CDC_ECM_STR_DESC_IDX, /* iFunction */ + + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ + _CDC_ECM_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoint used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x06, /* bInterfaceSubClass: Ethernet Control Model */ + 0x00, /* bInterfaceProtocol: No specific protocol required */ + 0x00, /* iInterface: */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header functional descriptor */ + 0x10, /* bcd CDC_ECM : spec release number: 1.20 */ + 0x01, + + /* CDC_ECM Functional Descriptor */ + 0x0D, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x0F, /* Ethernet Networking functional descriptor subtype */ + CDC_ECM_MAC_STRING_INDEX, /* Device's MAC string index */ + CDC_ECM_ETH_STATS_BYTE3, /* Ethernet statistics byte 3 (bitmap) */ + CDC_ECM_ETH_STATS_BYTE2, /* Ethernet statistics byte 2 (bitmap) */ + CDC_ECM_ETH_STATS_BYTE1, /* Ethernet statistics byte 1 (bitmap) */ + CDC_ECM_ETH_STATS_BYTE0, /* Ethernet statistics byte 0 (bitmap) */ + LOBYTE(CDC_ECM_ETH_MAX_SEGSZE), + HIBYTE(CDC_ECM_ETH_MAX_SEGSZE), /* wMaxSegmentSize: Ethernet Maximum Segment size, typically 1514 bytes */ + LOBYTE(CDC_ECM_ETH_NBR_MACFILTERS), + HIBYTE(CDC_ECM_ETH_NBR_MACFILTERS), /* wNumberMCFilters: the number of multicast filters */ + CDC_ECM_ETH_NBR_PWRFILTERS, /* bNumberPowerFilters: the number of wakeup power filters */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union functional descriptor */ + _CDC_ECM_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_ECM_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* Communication Endpoint Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_ECM_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_ECM_CMD_PACKET_SIZE), /* wMaxPacketSize */ + HIBYTE(CDC_ECM_CMD_PACKET_SIZE), + CDC_ECM_FS_BINTERVAL, /* bInterval */ + + /*----------------------*/ + + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: interface */ + _CDC_ECM_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass */ + 0x00, /* bInterfaceProtocol */ + 0x00, /* iInterface: */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_ECM_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + 0x40, /* wMaxPacketSize */ + 0x00, + 0xFF, /* bInterval: ignore for Bulk transfer */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_ECM_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + 0x40, /* wMaxPacketSize */ + 0x00, + 0xFF /* bInterval: ignore for Bulk transfer */ +}; + +/** + * @} + */ + +/** @defgroup USBD_CDC_ECM_Private_Functions + * @{ + */ + +/** + * @brief USBD_CDC_ECM_Init + * Initialize the CDC_ECM interface + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_CDC_ECM_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(cfgidx); + + USBD_CDC_ECM_HandleTypeDef *hcdc; + + hcdc = &CDC_ECM_Instance; + + if (hcdc == NULL) + { + pdev->pClassData_CDC_ECM = NULL; + return (uint8_t)USBD_EMEM; + } + + pdev->pClassData_CDC_ECM = (void *)hcdc; + + if (pdev->dev_speed == USBD_SPEED_HIGH) + { + /* Open EP IN */ + (void)USBD_LL_OpenEP(pdev, CDC_ECM_IN_EP, USBD_EP_TYPE_BULK, + CDC_ECM_DATA_HS_IN_PACKET_SIZE); + + pdev->ep_in[CDC_ECM_IN_EP & 0xFU].is_used = 1U; + + /* Open EP OUT */ + (void)USBD_LL_OpenEP(pdev, CDC_ECM_OUT_EP, USBD_EP_TYPE_BULK, + CDC_ECM_DATA_HS_OUT_PACKET_SIZE); + + pdev->ep_out[CDC_ECM_OUT_EP & 0xFU].is_used = 1U; + + /* Set bInterval for CDC ECM CMD Endpoint */ + pdev->ep_in[CDC_ECM_CMD_EP & 0xFU].bInterval = CDC_ECM_HS_BINTERVAL; + } + else + { + /* Open EP IN */ + (void)USBD_LL_OpenEP(pdev, CDC_ECM_IN_EP, USBD_EP_TYPE_BULK, + CDC_ECM_DATA_FS_IN_PACKET_SIZE); + + pdev->ep_in[CDC_ECM_IN_EP & 0xFU].is_used = 1U; + + /* Open EP OUT */ + (void)USBD_LL_OpenEP(pdev, CDC_ECM_OUT_EP, USBD_EP_TYPE_BULK, + CDC_ECM_DATA_FS_OUT_PACKET_SIZE); + + pdev->ep_out[CDC_ECM_OUT_EP & 0xFU].is_used = 1U; + + /* Set bInterval for CDC ECM CMD Endpoint */ + pdev->ep_in[CDC_ECM_CMD_EP & 0xFU].bInterval = CDC_ECM_FS_BINTERVAL; + } + + /* Open Command IN EP */ + (void)USBD_LL_OpenEP(pdev, CDC_ECM_CMD_EP, USBD_EP_TYPE_INTR, CDC_ECM_CMD_PACKET_SIZE); + pdev->ep_in[CDC_ECM_CMD_EP & 0xFU].is_used = 1U; + + /* Init physical Interface components */ + ((USBD_CDC_ECM_ItfTypeDef *)pdev->pUserData_CDC_ECM)->Init(); + + /* Init Xfer states */ + hcdc->TxState = 0U; + hcdc->RxState = 0U; + hcdc->RxLength = 0U; + hcdc->TxLength = 0U; + hcdc->LinkStatus = 0U; + hcdc->NotificationStatus = 0U; + hcdc->MaxPcktLen = (pdev->dev_speed == USBD_SPEED_HIGH) ? CDC_ECM_DATA_HS_MAX_PACKET_SIZE : CDC_ECM_DATA_FS_MAX_PACKET_SIZE; + + /* Prepare Out endpoint to receive next packet */ + (void)USBD_LL_PrepareReceive(pdev, CDC_ECM_OUT_EP, hcdc->RxBuffer, hcdc->MaxPcktLen); + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_ECM_DeInit + * DeInitialize the CDC_ECM layer + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_CDC_ECM_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(cfgidx); + + /* Close EP IN */ + (void)USBD_LL_CloseEP(pdev, CDC_ECM_IN_EP); + pdev->ep_in[CDC_ECM_IN_EP & 0xFU].is_used = 0U; + + /* Close EP OUT */ + (void)USBD_LL_CloseEP(pdev, CDC_ECM_OUT_EP); + pdev->ep_out[CDC_ECM_OUT_EP & 0xFU].is_used = 0U; + + /* Close Command IN EP */ + (void)USBD_LL_CloseEP(pdev, CDC_ECM_CMD_EP); + pdev->ep_in[CDC_ECM_CMD_EP & 0xFU].is_used = 0U; + pdev->ep_in[CDC_ECM_CMD_EP & 0xFU].bInterval = 0U; + + /* DeInit physical Interface components */ + if (pdev->pClassData_CDC_ECM != NULL) + { + ((USBD_CDC_ECM_ItfTypeDef *)pdev->pUserData_CDC_ECM)->DeInit(); +#if (0) + USBD_free(pdev->pClassData_CDC_ECM); +#endif + pdev->pClassData_CDC_ECM = NULL; + } + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_ECM_Setup + * Handle the CDC_ECM specific requests + * @param pdev: instance + * @param req: usb requests + * @retval status + */ +static uint8_t USBD_CDC_ECM_Setup(USBD_HandleTypeDef *pdev, + USBD_SetupReqTypedef *req) +{ + USBD_CDC_ECM_HandleTypeDef *hcdc = (USBD_CDC_ECM_HandleTypeDef *)pdev->pClassData_CDC_ECM; + USBD_CDC_ECM_ItfTypeDef *EcmInterface = (USBD_CDC_ECM_ItfTypeDef *)pdev->pUserData_CDC_ECM; + USBD_StatusTypeDef ret = USBD_OK; + uint16_t len; + uint16_t status_info = 0U; + uint8_t ifalt = 0U; + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + switch (req->bmRequest & USB_REQ_TYPE_MASK) + { + case USB_REQ_TYPE_CLASS: + if (req->wLength != 0U) + { + if ((req->bmRequest & 0x80U) != 0U) + { + EcmInterface->Control(req->bRequest, + (uint8_t *)hcdc->data, req->wLength); + + len = MIN(CDC_ECM_DATA_BUFFER_SIZE, req->wLength); + (void)USBD_CtlSendData(pdev, (uint8_t *)hcdc->data, len); + } + else + { + hcdc->CmdOpCode = req->bRequest; + hcdc->CmdLength = (uint8_t)MIN(req->wLength, USB_MAX_EP0_SIZE); + + (void)USBD_CtlPrepareRx(pdev, (uint8_t *)hcdc->data, hcdc->CmdLength); + } + } + else + { + EcmInterface->Control(req->bRequest, (uint8_t *)req, 0U); + } + break; + + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) + { + case USB_REQ_GET_STATUS: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_GET_INTERFACE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, &ifalt, 1U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_SET_INTERFACE: + if (pdev->dev_state != USBD_STATE_CONFIGURED) + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_CLEAR_FEATURE: + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + + return (uint8_t)ret; +} + +/** + * @brief USBD_CDC_ECM_DataIn + * Data sent on non-control IN endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +static uint8_t USBD_CDC_ECM_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + USBD_CDC_ECM_HandleTypeDef *hcdc = (USBD_CDC_ECM_HandleTypeDef *)pdev->pClassData_CDC_ECM; + PCD_HandleTypeDef *hpcd = pdev->pData; + + if (pdev->pClassData_CDC_ECM == NULL) + { + return (uint8_t)USBD_FAIL; + } + + if (epnum == (CDC_ECM_IN_EP & 0x7FU)) + { + if ((pdev->ep_in[epnum].total_length > 0U) && + ((pdev->ep_in[epnum].total_length % hpcd->IN_ep[epnum].maxpacket) == 0U)) + { + /* Update the packet total length */ + pdev->ep_in[epnum].total_length = 0U; + + /* Send ZLP */ + (void)USBD_LL_Transmit(pdev, epnum, NULL, 0U); + } + else + { + hcdc->TxState = 0U; + if (((USBD_CDC_ECM_ItfTypeDef *)pdev->pUserData_CDC_ECM)->TransmitCplt != NULL) + { + ((USBD_CDC_ECM_ItfTypeDef *)pdev->pUserData_CDC_ECM)->TransmitCplt(hcdc->TxBuffer, &hcdc->TxLength, epnum); + } + } + } + else if (epnum == (CDC_ECM_CMD_EP & 0x7FU)) + { + if (hcdc->NotificationStatus != 0U) + { + (void)USBD_CDC_ECM_SendNotification(pdev, ECM_CONNECTION_SPEED_CHANGE, + 0U, (uint8_t *)ConnSpeedTab); + + hcdc->NotificationStatus = 0U; + } + } + else + { + return (uint8_t)USBD_FAIL; + } + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_ECM_DataOut + * Data received on non-control Out endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +static uint8_t USBD_CDC_ECM_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + USBD_CDC_ECM_HandleTypeDef *hcdc = (USBD_CDC_ECM_HandleTypeDef *)pdev->pClassData_CDC_ECM; + uint32_t CurrPcktLen; + + if (pdev->pClassData_CDC_ECM == NULL) + { + return (uint8_t)USBD_FAIL; + } + + if (epnum == CDC_ECM_OUT_EP) + { + /* Get the received data length */ + CurrPcktLen = USBD_LL_GetRxDataSize(pdev, epnum); + + /* Increment the frame length */ + hcdc->RxLength += CurrPcktLen; + + /* If the buffer size is less than max packet size: it is the last packet in current frame */ + if ((CurrPcktLen < hcdc->MaxPcktLen) || (hcdc->RxLength >= CDC_ECM_ETH_MAX_SEGSZE)) + { + /* USB data will be immediately processed, this allow next USB traffic being + NAKed till the end of the application Xfer */ + + /* Process data by application (ie. copy to app buffer or notify user) + hcdc->RxLength must be reset to zero at the end of the call of this function */ + ((USBD_CDC_ECM_ItfTypeDef *)pdev->pUserData_CDC_ECM)->Receive(hcdc->RxBuffer, &hcdc->RxLength); + } + else + { + /* Prepare Out endpoint to receive next packet in current/new frame */ + (void)USBD_LL_PrepareReceive(pdev, CDC_ECM_OUT_EP, + (uint8_t *)(hcdc->RxBuffer + hcdc->RxLength), + hcdc->MaxPcktLen); + } + } + else + { + return (uint8_t)USBD_FAIL; + } + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_ECM_EP0_RxReady + * Handle EP0 Rx Ready event + * @param pdev: device instance + * @retval status + */ +static uint8_t USBD_CDC_ECM_EP0_RxReady(USBD_HandleTypeDef *pdev) +{ + USBD_CDC_ECM_HandleTypeDef *hcdc = (USBD_CDC_ECM_HandleTypeDef *)pdev->pClassData_CDC_ECM; + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + if ((pdev->pUserData_CDC_ECM != NULL) && (hcdc->CmdOpCode != 0xFFU)) + { + ((USBD_CDC_ECM_ItfTypeDef *)pdev->pUserData_CDC_ECM)->Control(hcdc->CmdOpCode, (uint8_t *)hcdc->data, (uint16_t)hcdc->CmdLength); + hcdc->CmdOpCode = 0xFFU; + } + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_ECM_GetFSCfgDesc + * Return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CDC_ECM_GetFSCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_CDC_ECM_CfgFSDesc); + + return USBD_CDC_ECM_CfgFSDesc; +} + +/** + * @brief USBD_CDC_ECM_GetHSCfgDesc + * Return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CDC_ECM_GetHSCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_CDC_ECM_CfgHSDesc); + + return USBD_CDC_ECM_CfgHSDesc; +} + +/** + * @brief USBD_CDC_ECM_GetCfgDesc + * Return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CDC_ECM_GetOtherSpeedCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_CDC_ECM_OtherSpeedCfgDesc); + + return USBD_CDC_ECM_OtherSpeedCfgDesc; +} + +/** + * @brief DeviceQualifierDescriptor + * return Device Qualifier descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +uint8_t *USBD_CDC_ECM_GetDeviceQualifierDescriptor(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_CDC_ECM_DeviceQualifierDesc); + + return USBD_CDC_ECM_DeviceQualifierDesc; +} + +/** + * @brief USBD_CDC_ECM_RegisterInterface + * @param pdev: device instance + * @param fops: CD Interface callback + * @retval status + */ +uint8_t USBD_CDC_ECM_RegisterInterface(USBD_HandleTypeDef *pdev, + USBD_CDC_ECM_ItfTypeDef *fops) +{ + if (fops == NULL) + { + return (uint8_t)USBD_FAIL; + } + + pdev->pUserData_CDC_ECM = fops; + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_ECM_USRStringDescriptor + * Manages the transfer of user string descriptors. + * @param speed : current device speed + * @param index: descriptor index + * @param length : pointer data length + * @retval pointer to the descriptor table or NULL if the descriptor is not supported. + */ +#if (USBD_SUPPORT_USER_STRING_DESC == 1U) +static uint8_t *USBD_CDC_ECM_USRStringDescriptor(USBD_HandleTypeDef *pdev, uint8_t index, uint16_t *length) +{ + static uint8_t USBD_StrDesc[255]; + + /* Check if the requested string interface is supported */ + if (index == CDC_ECM_MAC_STRING_INDEX) + { + USBD_GetString((uint8_t *)((USBD_CDC_ECM_ItfTypeDef *)pdev->pUserData_CDC_ECM)->pStrDesc, USBD_StrDesc, length); + return USBD_StrDesc; + } + /* Not supported Interface Descriptor index */ + else + { + return NULL; + } +} +#endif + +/** + * @brief USBD_CDC_ECM_SetTxBuffer + * @param pdev: device instance + * @param pbuff: Tx Buffer + * @retval status + */ +uint8_t USBD_CDC_ECM_SetTxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff, uint32_t length) +{ + USBD_CDC_ECM_HandleTypeDef *hcdc = (USBD_CDC_ECM_HandleTypeDef *)pdev->pClassData_CDC_ECM; + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + hcdc->TxBuffer = pbuff; + hcdc->TxLength = length; + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_ECM_SetRxBuffer + * @param pdev: device instance + * @param pbuff: Rx Buffer + * @retval status + */ +uint8_t USBD_CDC_ECM_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff) +{ + USBD_CDC_ECM_HandleTypeDef *hcdc = (USBD_CDC_ECM_HandleTypeDef *)pdev->pClassData_CDC_ECM; + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + hcdc->RxBuffer = pbuff; + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_ECM_TransmitPacket + * Transmit packet on IN endpoint + * @param pdev: device instance + * @retval status + */ +uint8_t USBD_CDC_ECM_TransmitPacket(USBD_HandleTypeDef *pdev) +{ + USBD_CDC_ECM_HandleTypeDef *hcdc = (USBD_CDC_ECM_HandleTypeDef *)pdev->pClassData_CDC_ECM; + USBD_StatusTypeDef ret = USBD_BUSY; + + if (pdev->pClassData_CDC_ECM == NULL) + { + return (uint8_t)USBD_FAIL; + } + + if (hcdc->TxState == 0U) + { + /* Tx Transfer in progress */ + hcdc->TxState = 1U; + + /* Update the packet total length */ + pdev->ep_in[CDC_ECM_IN_EP & 0xFU].total_length = hcdc->TxLength; + + /* Transmit next packet */ + (void)USBD_LL_Transmit(pdev, CDC_ECM_IN_EP, hcdc->TxBuffer, hcdc->TxLength); + + ret = USBD_OK; + } + + return (uint8_t)ret; +} + +/** + * @brief USBD_CDC_ECM_ReceivePacket + * prepare OUT Endpoint for reception + * @param pdev: device instance + * @retval status + */ +uint8_t USBD_CDC_ECM_ReceivePacket(USBD_HandleTypeDef *pdev) +{ + USBD_CDC_ECM_HandleTypeDef *hcdc = (USBD_CDC_ECM_HandleTypeDef *)pdev->pClassData_CDC_ECM; + + if (pdev->pClassData_CDC_ECM == NULL) + { + return (uint8_t)USBD_FAIL; + } + + /* Prepare Out endpoint to receive next packet */ + (void)USBD_LL_PrepareReceive(pdev, CDC_ECM_OUT_EP, hcdc->RxBuffer, hcdc->MaxPcktLen); + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_ECM_SendNotification + * Transmit Notification packet on CMD IN interrupt endpoint + * @param pdev: device instance + * Notif: value of the notification type (from CDC_ECM_Notification_TypeDef enumeration list) + * bVal: value of the notification switch (ie. 0x00 or 0x01 for Network Connection notification) + * pData: pointer to data buffer (ie. upstream and downstream connection speed values) + * @retval status + */ +uint8_t USBD_CDC_ECM_SendNotification(USBD_HandleTypeDef *pdev, + USBD_CDC_ECM_NotifCodeTypeDef Notif, + uint16_t bVal, uint8_t *pData) +{ + uint32_t Idx; + uint32_t ReqSize = 0U; + USBD_CDC_ECM_HandleTypeDef *hcdc = (USBD_CDC_ECM_HandleTypeDef *)pdev->pClassData_CDC_ECM; + USBD_StatusTypeDef ret = USBD_OK; + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + /* Initialize the request fields */ + (hcdc->Req).bmRequest = CDC_ECM_BMREQUEST_TYPE_ECM; + (hcdc->Req).bRequest = (uint8_t)Notif; + + switch ((hcdc->Req).bRequest) + { + case ECM_NETWORK_CONNECTION: + (hcdc->Req).wValue = bVal; + (hcdc->Req).wIndex = CDC_ECM_CMD_ITF_NBR; + (hcdc->Req).wLength = 0U; + + for (Idx = 0U; Idx < 8U; Idx++) + { + (hcdc->Req).data[Idx] = 0U; + } + ReqSize = 8U; + break; + + case ECM_RESPONSE_AVAILABLE: + (hcdc->Req).wValue = 0U; + (hcdc->Req).wIndex = CDC_ECM_CMD_ITF_NBR; + (hcdc->Req).wLength = 0U; + for (Idx = 0U; Idx < 8U; Idx++) + { + (hcdc->Req).data[Idx] = 0U; + } + ReqSize = 8U; + break; + + case ECM_CONNECTION_SPEED_CHANGE: + (hcdc->Req).wValue = 0U; + (hcdc->Req).wIndex = CDC_ECM_CMD_ITF_NBR; + (hcdc->Req).wLength = 0x0008U; + ReqSize = 16U; + + /* Check pointer to data buffer */ + if (pData != NULL) + { + for (Idx = 0U; Idx < 8U; Idx++) + { + (hcdc->Req).data[Idx] = pData[Idx]; + } + } + break; + + default: + ret = USBD_FAIL; + break; + } + + /* Transmit notification packet */ + if (ReqSize != 0U) + { + (void)USBD_LL_Transmit(pdev, CDC_ECM_CMD_EP, (uint8_t *)&(hcdc->Req), ReqSize); + } + + return (uint8_t)ret; +} + +void USBD_Update_CDC_ECM_DESC(uint8_t *desc, + uint8_t cmd_itf, + uint8_t com_itf, + uint8_t in_ep, + uint8_t cmd_ep, + uint8_t out_ep, + uint8_t str_idx) +{ + desc[11] = cmd_itf; + desc[16] = str_idx; + desc[19] = cmd_itf; + desc[47] = com_itf; + desc[48] = cmd_itf; + desc[51] = cmd_ep; + desc[58] = com_itf; + desc[67] = out_ep; + desc[74] = in_ep; + + CDC_ECM_IN_EP = in_ep; + CDC_ECM_OUT_EP = out_ep; + CDC_ECM_CMD_EP = cmd_ep; + CDC_ECM_CMD_ITF_NBR = cmd_itf; + CDC_ECM_COM_ITF_NBR = com_itf; + CDC_ECM_STR_DESC_IDX = str_idx; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/CDC_RNDIS/Inc/usbd_cdc_rndis.h b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/CDC_RNDIS/Inc/usbd_cdc_rndis.h new file mode 100644 index 0000000..e3f4537 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/CDC_RNDIS/Inc/usbd_cdc_rndis.h @@ -0,0 +1,530 @@ +/** + ****************************************************************************** + * @file usbd_cdc_rndis.h + * @author MCD Application Team + * @brief header file for the usbd_cdc_rndis.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_CDC_RNDIS_H +#define __USB_CDC_RNDIS_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ioreq.h" + + /** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + + /** @defgroup usbd_cdc_rndis + * @brief This file is the Header file for usbd_cdc_rndis.c + * @{ + */ + + /** @defgroup usbd_cdc_rndis_Exported_Defines + * @{ + */ + +#define CDC_RNDIS_STR_DESC "STM32 CDC RNDIS" + +#ifndef CDC_RNDIS_HS_BINTERVAL +#define CDC_RNDIS_HS_BINTERVAL 0x10U +#endif /* CDC_RNDIS_HS_BINTERVAL */ + +#ifndef CDC_RNDIS_FS_BINTERVAL +#define CDC_RNDIS_FS_BINTERVAL 0x10U +#endif /* CDC_RNDIS_FS_BINTERVAL */ + + +/* CDC_RNDIS Endpoints parameters: you can fine tune these values + depending on the needed baudrates and performance. */ +#define CDC_RNDIS_DATA_HS_MAX_PACKET_SIZE 512U /* Endpoint IN & OUT Packet size */ +#define CDC_RNDIS_DATA_FS_MAX_PACKET_SIZE 64U /* Endpoint IN & OUT Packet size */ +#define CDC_RNDIS_CMD_PACKET_SIZE 16U /* Control Endpoint Packet size */ + +#define CDC_RNDIS_CONFIG_DESC_SIZE 75U +#define CDC_RNDIS_DATA_HS_IN_PACKET_SIZE CDC_RNDIS_DATA_HS_MAX_PACKET_SIZE +#define CDC_RNDIS_DATA_HS_OUT_PACKET_SIZE CDC_RNDIS_DATA_HS_MAX_PACKET_SIZE + +#define CDC_RNDIS_DATA_FS_IN_PACKET_SIZE CDC_RNDIS_DATA_FS_MAX_PACKET_SIZE +#define CDC_RNDIS_DATA_FS_OUT_PACKET_SIZE CDC_RNDIS_DATA_FS_MAX_PACKET_SIZE + +/*---------------------------------------------------------------------*/ +/* CDC_RNDIS definitions */ +/*---------------------------------------------------------------------*/ + +/** Implemented CDC_RNDIS Version Major */ +#define CDC_RNDIS_VERSION_MAJOR 0x01U + +/* Implemented CDC_RNDIS Version Minor */ +#define CDC_RNDIS_VERSION_MINOR 0x00U + +/* Maximum size in bytes of a CDC_RNDIS control message + which can be sent or received */ +#define CDC_RNDIS_MESSAGE_BUFFER_SIZE 128U + +/* Maximum size in bytes of an Ethernet frame + according to the Ethernet standard */ +#define CDC_RNDIS_ETH_FRAME_SIZE_MAX 1536U + +/* Maximum size allocated for buffer + inside Query messages structures */ +#define CDC_RNDIS_MAX_INFO_BUFF_SZ 200U +#define CDC_RNDIS_MAX_DATA_SZE 2000U + +/* Notification request value for a CDC_RNDIS + Response Available notification */ +#define CDC_RNDIS_NOTIFICATION_RESP_AVAILABLE 0x00000001UL + + +#define CDC_RNDIS_PACKET_MSG_ID 0x00000001UL +#define CDC_RNDIS_INITIALIZE_MSG_ID 0x00000002UL +#define CDC_RNDIS_HALT_MSG_ID 0x00000003UL +#define CDC_RNDIS_QUERY_MSG_ID 0x00000004UL +#define CDC_RNDIS_SET_MSG_ID 0x00000005UL +#define CDC_RNDIS_RESET_MSG_ID 0x00000006UL +#define CDC_RNDIS_INDICATE_STATUS_MSG_ID 0x00000007UL +#define CDC_RNDIS_KEEPALIVE_MSG_ID 0x00000008UL + +#define CDC_RNDIS_INITIALIZE_CMPLT_ID 0x80000002UL +#define CDC_RNDIS_QUERY_CMPLT_ID 0x80000004UL +#define CDC_RNDIS_SET_CMPLT_ID 0x80000005UL +#define CDC_RNDIS_RESET_CMPLT_ID 0x80000006UL +#define CDC_RNDIS_KEEPALIVE_CMPLT_ID 0x80000008UL + +#define CDC_RNDIS_STATUS_SUCCESS 0x00000000UL +#define CDC_RNDIS_STATUS_FAILURE 0xC0000001UL +#define CDC_RNDIS_STATUS_INVALID_DATA 0xC0010015UL +#define CDC_RNDIS_STATUS_NOT_SUPPORTED 0xC00000BBUL +#define CDC_RNDIS_STATUS_MEDIA_CONNECT 0x4001000BUL +#define CDC_RNDIS_STATUS_MEDIA_DISCONNECT 0x4001000CUL +/** Media state */ +#define CDC_RNDIS_MEDIA_STATE_CONNECTED 0x00000000UL +#define CDC_RNDIS_MEDIA_STATE_DISCONNECTED 0x00000001UL + +/** Media types */ +#define CDC_RNDIS_MEDIUM_802_3 0x00000000UL + +#define CDC_RNDIS_DF_CONNECTIONLESS 0x00000001UL +#define CDC_RNDIS_DF_CONNECTION_ORIENTED 0x00000002UL + +/** Hardware status of the underlying NIC */ +#define CDC_RNDIS_HW_STS_READY 0x00000000UL +#define CDC_RNDIS_HW_STS_INITIALIZING 0x00000001UL +#define CDC_RNDIS_HW_STS_RESET 0x00000002UL +#define CDC_RNDIS_HW_STS_CLOSING 0x00000003UL +#define CDC_RNDIS_HW_STS_NOT_READY 0x00000004UL + +/** Packet filter */ +#define CDC_RNDIS_PACKET_DIRECTED 0x00000001UL +#define CDC_RNDIS_PACKET_MULTICAST 0x00000002UL +#define CDC_RNDIS_PACKET_ALL_MULTICAST 0x00000004UL +#define CDC_RNDIS_PACKET_BROADCAST 0x00000008UL +#define CDC_RNDIS_PACKET_SOURCE_ROUTING 0x00000010UL +#define CDC_RNDIS_PACKET_PROMISCUOUS 0x00000020UL +#define CDC_RNDIS_PACKET_SMT 0x00000040UL +#define CDC_RNDIS_PACKET_ALL_LOCAL 0x00000080UL +#define CDC_RNDIS_PACKET_GROUP 0x00001000UL +#define CDC_RNDIS_PACKET_ALL_FUNCTIONAL 0x00002000UL +#define CDC_RNDIS_PACKET_FUNCTIONAL 0x00004000UL +#define CDC_RNDIS_PACKET_MAC_FRAME 0x00008000UL + +#define OID_GEN_SUPPORTED_LIST 0x00010101UL +#define OID_GEN_HARDWARE_STATUS 0x00010102UL +#define OID_GEN_MEDIA_SUPPORTED 0x00010103UL +#define OID_GEN_MEDIA_IN_USE 0x00010104UL +#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106UL +#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111UL +#define OID_GEN_LINK_SPEED 0x00010107UL +#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010AUL +#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010BUL +#define OID_GEN_VENDOR_ID 0x0001010CUL +#define OID_GEN_VENDOR_DESCRIPTION 0x0001010DUL +#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010EUL +#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114UL +#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115UL +#define OID_GEN_PHYSICAL_MEDIUM 0x00010202UL +#define OID_GEN_XMIT_OK 0x00020101UL +#define OID_GEN_RCV_OK 0x00020102UL +#define OID_GEN_XMIT_ERROR 0x00020103UL +#define OID_GEN_RCV_ERROR 0x00020104UL +#define OID_GEN_RCV_NO_BUFFER 0x00020105UL +#define OID_GEN_CDC_RNDIS_CONFIG_PARAMETER 0x0001021BUL +#define OID_802_3_PERMANENT_ADDRESS 0x01010101UL +#define OID_802_3_CURRENT_ADDRESS 0x01010102UL +#define OID_802_3_MULTICAST_LIST 0x01010103UL +#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104UL +#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101UL +#define OID_802_3_XMIT_ONE_COLLISION 0x01020102UL +#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103UL + + +#define CDC_RNDIS_SEND_ENCAPSULATED_COMMAND 0x00U +#define CDC_RNDIS_GET_ENCAPSULATED_RESPONSE 0x01U + +#define CDC_RNDIS_NET_DISCONNECTED 0x00U +#define CDC_RNDIS_NET_CONNECTED 0x01U + +#define CDC_RNDIS_BMREQUEST_TYPE_RNDIS 0xA1U +#define CDC_RNDIS_PCKTMSG_DATAOFFSET_OFFSET 8U + +/* MAC String index */ +#define CDC_RNDIS_MAC_STRING_INDEX 6U + +/** + * @} + */ + + +/** @defgroup USBD_CORE_Exported_TypesDefinitions + * @{ + */ + +/** + * @} + */ + + typedef struct _USBD_CDC_RNDIS_Itf + { + int8_t (*Init)(void); + int8_t (*DeInit)(void); + int8_t (*Control)(uint8_t cmd, uint8_t *pbuf, uint16_t length); + int8_t (*Receive)(uint8_t *Buf, uint32_t *Len); + int8_t (*TransmitCplt)(uint8_t *Buf, uint32_t *Len, uint8_t epnum); + int8_t (*Process)(USBD_HandleTypeDef *pdev); + uint8_t *pStrDesc; + } USBD_CDC_RNDIS_ItfTypeDef; + + /* CDC_RNDIS State values */ + typedef enum + { + CDC_RNDIS_STATE_UNINITIALIZED = 0, + CDC_RNDIS_STATE_BUS_INITIALIZED = 1, + CDC_RNDIS_STATE_INITIALIZED = 2, + CDC_RNDIS_STATE_DATA_INITIALIZED = 3 + } USBD_CDC_RNDIS_StateTypeDef; + + typedef struct + { + uint8_t bmRequest; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; + uint8_t data[8]; + } USBD_CDC_RNDIS_NotifTypeDef; + + typedef struct + { + uint32_t data[CDC_RNDIS_MAX_DATA_SZE / 4U]; /* Force 32-bit alignment */ + uint8_t CmdOpCode; + uint8_t CmdLength; + uint8_t ResponseRdy; /* Indicates if the Device Response to an CDC_RNDIS msg is ready */ + uint8_t Reserved1; /* Reserved Byte to force 4 bytes alignment of following fields */ + uint8_t *RxBuffer; + uint8_t *TxBuffer; + uint32_t RxLength; + uint32_t TxLength; + + USBD_CDC_RNDIS_NotifTypeDef Req; + USBD_CDC_RNDIS_StateTypeDef State; + + __IO uint32_t TxState; + __IO uint32_t RxState; + + __IO uint32_t MaxPcktLen; + __IO uint32_t LinkStatus; + __IO uint32_t NotificationStatus; + __IO uint32_t PacketFilter; + } USBD_CDC_RNDIS_HandleTypeDef; + + typedef enum + { + RNDIS_NETWORK_CONNECTION = 0x00, + RNDIS_RESPONSE_AVAILABLE = 0x01, + RNDIS_CONNECTION_SPEED_CHANGE = 0x2A + } USBD_CDC_RNDIS_NotifCodeTypeDef; + + /* Messages Sent by the Host ---------------------*/ + + /* Type define for a CDC_RNDIS Initialize command message */ + typedef struct + { + uint32_t MsgType; + uint32_t MsgLength; + uint32_t ReqId; + uint32_t MajorVersion; + uint32_t MinorVersion; + uint32_t MaxTransferSize; + } USBD_CDC_RNDIS_InitMsgTypeDef; + + /* Type define for a CDC_RNDIS Halt Message */ + typedef struct + { + uint32_t MsgType; + uint32_t MsgLength; + uint32_t ReqId; + } USBD_CDC_RNDIS_HaltMsgTypeDef; + + /* Type define for a CDC_RNDIS Query command message */ + typedef struct + { + uint32_t MsgType; + uint32_t MsgLength; + uint32_t RequestId; + uint32_t Oid; + uint32_t InfoBufLength; + uint32_t InfoBufOffset; + uint32_t DeviceVcHandle; + uint32_t InfoBuf[CDC_RNDIS_MAX_INFO_BUFF_SZ]; + } USBD_CDC_RNDIS_QueryMsgTypeDef; + + /* Type define for a CDC_RNDIS Set command message */ + typedef struct + { + uint32_t MsgType; + uint32_t MsgLength; + uint32_t ReqId; + uint32_t Oid; + uint32_t InfoBufLength; + uint32_t InfoBufOffset; + uint32_t DeviceVcHandle; + uint32_t InfoBuf[CDC_RNDIS_MAX_INFO_BUFF_SZ]; + } USBD_CDC_RNDIS_SetMsgTypeDef; + + /* Type define for a CDC_RNDIS Reset message */ + typedef struct + { + uint32_t MsgType; + uint32_t MsgLength; + uint32_t Reserved; + } USBD_CDC_RNDIS_ResetMsgTypeDef; + + /* Type define for a CDC_RNDIS Keepalive command message */ + typedef struct + { + uint32_t MsgType; + uint32_t MsgLength; + uint32_t ReqId; + } USBD_CDC_RNDIS_KpAliveMsgTypeDef; + + /* Messages Sent by the Device ---------------------*/ + + /* Type define for a CDC_RNDIS Initialize complete response message */ + typedef struct + { + uint32_t MsgType; + uint32_t MsgLength; + uint32_t ReqId; + uint32_t Status; + uint32_t MajorVersion; + uint32_t MinorVersion; + uint32_t DeviceFlags; + uint32_t Medium; + uint32_t MaxPacketsPerTransfer; + uint32_t MaxTransferSize; + uint32_t PacketAlignmentFactor; + uint32_t AFListOffset; + uint32_t AFListSize; + } USBD_CDC_RNDIS_InitCpltMsgTypeDef; + + /* Type define for a CDC_RNDIS Query complete response message */ + typedef struct + { + uint32_t MsgType; + uint32_t MsgLength; + uint32_t ReqId; + uint32_t Status; + uint32_t InfoBufLength; + uint32_t InfoBufOffset; + uint32_t InfoBuf[CDC_RNDIS_MAX_INFO_BUFF_SZ]; + } USBD_CDC_RNDIS_QueryCpltMsgTypeDef; + + /* Type define for a CDC_RNDIS Set complete response message */ + typedef struct + { + uint32_t MsgType; + uint32_t MsgLength; + uint32_t ReqId; + uint32_t Status; + } USBD_CDC_RNDIS_SetCpltMsgTypeDef; + + /* Type define for a CDC_RNDIS Reset complete message */ + typedef struct + { + uint32_t MsgType; + uint32_t MsgLength; + uint32_t Status; + uint32_t AddrReset; + } USBD_CDC_RNDIS_ResetCpltMsgTypeDef; + + /* Type define for CDC_RNDIS struct to indicate a change + in the status of the device */ + typedef struct + { + uint32_t MsgType; + uint32_t MsgLength; + uint32_t Status; + uint32_t StsBufLength; + uint32_t StsBufOffset; + } USBD_CDC_RNDIS_StsChangeMsgTypeDef; + + /* Type define for a CDC_RNDIS Keepalive complete message */ + typedef struct + { + uint32_t MsgType; + uint32_t MsgLength; + uint32_t ReqId; + uint32_t Status; + } USBD_CDC_RNDIS_KpAliveCpltMsgTypeDef; + + /* Messages Sent by both Host and Device ---------------------*/ + + /* Type define for a CDC_RNDIS packet message, used to encapsulate + Ethernet packets sent to and from the adapter */ + typedef struct + { + uint32_t MsgType; + uint32_t MsgLength; + uint32_t DataOffset; + uint32_t DataLength; + uint32_t OOBDataOffset; + uint32_t OOBDataLength; + uint32_t NumOOBDataElements; + uint32_t PerPacketInfoOffset; + uint32_t PerPacketInfoLength; + uint32_t VcHandle; + uint32_t Reserved; + } USBD_CDC_RNDIS_PacketMsgTypeDef; + + /* Miscellaneous types used for parsing ---------------------*/ + + /* The common part for all CDC_RNDIS messages Complete response */ + typedef struct + { + uint32_t MsgType; + uint32_t MsgLength; + uint32_t ReqId; + uint32_t Status; + } USBD_CDC_RNDIS_CommonCpltMsgTypeDef; + + /* Type define for a single parameter structure */ + typedef struct + { + uint32_t ParamNameOffset; + uint32_t ParamNameLength; + uint32_t ParamType; + uint32_t ParamValueOffset; + uint32_t ParamValueLength; + } USBD_CDC_RNDIS_ParamStructTypeDef; + + /* Type define of a single CDC_RNDIS OOB data record */ + typedef struct + { + uint32_t Size; + uint32_t Type; + uint32_t ClassInfoType; + uint32_t OOBData[sizeof(uint32_t)]; + } USBD_CDC_RNDIS_OOBPacketTypeDef; + + /* Type define for notification structure */ + typedef struct + { + uint32_t notification; + uint32_t reserved; + } USBD_CDC_RNDIS_NotifStructTypeDef; + + /* This structure will be used to store the type, the size and ID for any + received message from the control endpoint */ + typedef struct + { + uint32_t MsgType; + uint32_t MsgLength; + } USBD_CDC_RNDIS_CtrlMsgTypeDef; + + /** @defgroup USBD_CORE_Exported_Macros + * @{ + */ + + /** + * @} + */ + + /** @defgroup USBD_CORE_Exported_Variables + * @{ + */ + + extern USBD_ClassTypeDef USBD_CDC_RNDIS; + + extern uint8_t CDC_RNDIS_IN_EP; + extern uint8_t CDC_RNDIS_OUT_EP; + extern uint8_t CDC_RNDIS_CMD_EP; + + extern uint8_t CDC_RNDIS_CMD_ITF_NBR; + extern uint8_t CDC_RNDIS_COM_ITF_NBR; + extern uint8_t CDC_RNDIS_STR_DESC_IDX; + + /** + * @} + */ + + /** @defgroup USB_CORE_Exported_Functions + * @{ + */ + uint8_t USBD_CDC_RNDIS_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff); + uint8_t USBD_CDC_RNDIS_ReceivePacket(USBD_HandleTypeDef *pdev); + uint8_t USBD_CDC_RNDIS_TransmitPacket(USBD_HandleTypeDef *pdev); + + uint8_t USBD_CDC_RNDIS_RegisterInterface(USBD_HandleTypeDef *pdev, + USBD_CDC_RNDIS_ItfTypeDef *fops); + + uint8_t USBD_CDC_RNDIS_SetTxBuffer(USBD_HandleTypeDef *pdev, + uint8_t *pbuff, uint32_t length); + + uint8_t USBD_CDC_RNDIS_SendNotification(USBD_HandleTypeDef *pdev, + USBD_CDC_RNDIS_NotifCodeTypeDef Notif, + uint16_t bVal, uint8_t *pData); + + void USBD_Update_CDC_RNDIS_DESC(uint8_t *desc, + uint8_t cmd_itf, + uint8_t com_itf, + uint8_t in_ep, + uint8_t cmd_ep, + uint8_t out_ep, + uint8_t str_idx); + + /** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_CDC_RNDIS_H */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/CDC_RNDIS/Src/usbd_cdc_rndis.c b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/CDC_RNDIS/Src/usbd_cdc_rndis.c new file mode 100644 index 0000000..529ce4a --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/CDC_RNDIS/Src/usbd_cdc_rndis.c @@ -0,0 +1,1800 @@ +/** + ****************************************************************************** + * @file usbd_cdc_rndis.c + * @author MCD Application Team + * @brief This file provides the high layer firmware functions to manage the + * following functionalities of the USB CDC_RNDIS Class: + * - Initialization and Configuration of high and low layer + * - Enumeration as CDC_RNDIS Device (and enumeration for each implemented memory interface) + * - OUT/IN data transfer + * - Command IN transfer (class requests management) + * - Error management + * + * @verbatim + * + * =================================================================== + * CDC_RNDIS Class Driver Description + * =================================================================== + * This driver manages the "Universal Serial Bus Class Definitions for Communications Devices + * Revision 1.2 November 16, 2007" and the sub-protocol specification of "Universal Serial Bus + * Communications Class Subclass Specification for PSTN Devices Revision 1.2 February 9, 2007" + * This driver implements the following aspects of the specification: + * - Device descriptor management + * - Configuration descriptor management + * - Enumeration as CDC device with 2 data endpoints (IN and OUT) and 1 command endpoint (IN) + * - Requests management (as described in section 6.2 in specification) + * - Abstract Control Model compliant + * - Union Functional collection (using 1 IN endpoint for control) + * - Data interface class + * + * These aspects may be enriched or modified for a specific user application. + * + * This driver doesn't implement the following aspects of the specification + * (but it is possible to manage these features with some modifications on this driver): + * - Any class-specific aspect relative to communication classes should be managed by user application. + * - All communication classes other than PSTN are not managed + * + * @endverbatim + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_cdc_rndis.h" +#include "usbd_ctlreq.h" + +#include "usbd_cdc_rndis_if.h" + +#define _CDC_RNDIS_IN_EP 0x81U /* EP1 for data IN */ +#define _CDC_RNDIS_OUT_EP 0x01U /* EP1 for data OUT */ +#define _CDC_RNDIS_CMD_EP 0x82U /* EP2 for CDC_RNDIS commands */ +#define _CDC_RNDIS_CMD_ITF_NBR 0x00U /* Command Interface Number 0 */ +#define _CDC_RNDIS_COM_ITF_NBR 0x01U /* Communication Interface Number 0 */ +#define _CDC_RNDIS_STR_DESC_IDX 0x00U + +uint8_t CDC_RNDIS_IN_EP = _CDC_RNDIS_IN_EP; +uint8_t CDC_RNDIS_OUT_EP = _CDC_RNDIS_OUT_EP; +uint8_t CDC_RNDIS_CMD_EP = _CDC_RNDIS_CMD_EP; +uint8_t CDC_RNDIS_CMD_ITF_NBR = _CDC_RNDIS_CMD_ITF_NBR; +uint8_t CDC_RNDIS_COM_ITF_NBR = _CDC_RNDIS_COM_ITF_NBR; +uint8_t CDC_RNDIS_STR_DESC_IDX = _CDC_RNDIS_STR_DESC_IDX; + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_CDC_RNDIS + * @brief usbd core module + * @{ + */ + +/** @defgroup USBD_CDC_RNDIS_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_CDC_RNDIS_Private_Defines + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_CDC_RNDIS_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_RNDIS_Private_FunctionPrototypes + * @{ + */ + +static uint8_t USBD_CDC_RNDIS_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_CDC_RNDIS_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx); + +static uint8_t USBD_CDC_RNDIS_Setup(USBD_HandleTypeDef *pdev, + USBD_SetupReqTypedef *req); + +static uint8_t USBD_CDC_RNDIS_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum); +static uint8_t USBD_CDC_RNDIS_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum); +static uint8_t USBD_CDC_RNDIS_EP0_RxReady(USBD_HandleTypeDef *pdev); +static uint8_t *USBD_CDC_RNDIS_GetFSCfgDesc(uint16_t *length); +static uint8_t *USBD_CDC_RNDIS_GetHSCfgDesc(uint16_t *length); +static uint8_t *USBD_CDC_RNDIS_GetOtherSpeedCfgDesc(uint16_t *length); +static uint8_t *USBD_CDC_RNDIS_GetOtherSpeedCfgDesc(uint16_t *length); + +#if (USBD_SUPPORT_USER_STRING_DESC == 1U) +static uint8_t *USBD_CDC_RNDIS_USRStringDescriptor(USBD_HandleTypeDef *pdev, uint8_t index, uint16_t *length); +#endif + +uint8_t *USBD_CDC_RNDIS_GetDeviceQualifierDescriptor(uint16_t *length); + +/* CDC_RNDIS Internal messages parsing and construction functions */ +static uint8_t USBD_CDC_RNDIS_MsgParsing(USBD_HandleTypeDef *pdev, uint8_t *RxBuff); +static uint8_t USBD_CDC_RNDIS_ProcessInitMsg(USBD_HandleTypeDef *pdev, USBD_CDC_RNDIS_InitMsgTypeDef *Msg); +static uint8_t USBD_CDC_RNDIS_ProcessHaltMsg(USBD_HandleTypeDef *pdev, USBD_CDC_RNDIS_HaltMsgTypeDef *Msg); +static uint8_t USBD_CDC_RNDIS_ProcessKeepAliveMsg(USBD_HandleTypeDef *pdev, USBD_CDC_RNDIS_KpAliveMsgTypeDef *Msg); +static uint8_t USBD_CDC_RNDIS_ProcessQueryMsg(USBD_HandleTypeDef *pdev, USBD_CDC_RNDIS_QueryMsgTypeDef *Msg); +static uint8_t USBD_CDC_RNDIS_ProcessSetMsg(USBD_HandleTypeDef *pdev, USBD_CDC_RNDIS_SetMsgTypeDef *Msg); +static uint8_t USBD_CDC_RNDIS_ProcessResetMsg(USBD_HandleTypeDef *pdev, USBD_CDC_RNDIS_ResetMsgTypeDef *Msg); +static uint8_t USBD_CDC_RNDIS_ProcessPacketMsg(USBD_HandleTypeDef *pdev, USBD_CDC_RNDIS_PacketMsgTypeDef *Msg); +static uint8_t USBD_CDC_RNDIS_ProcessUnsupportedMsg(USBD_HandleTypeDef *pdev, USBD_CDC_RNDIS_CtrlMsgTypeDef *Msg); + +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_CDC_RNDIS_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, +}; + +static uint8_t MAC_StrDesc[6] = {CDC_RNDIS_MAC_ADDR0, CDC_RNDIS_MAC_ADDR1, CDC_RNDIS_MAC_ADDR2, + CDC_RNDIS_MAC_ADDR3, CDC_RNDIS_MAC_ADDR4, CDC_RNDIS_MAC_ADDR5}; + +static uint32_t ConnSpeedTab[2] = {CDC_RNDIS_CONNECT_SPEED_UPSTREAM, + CDC_RNDIS_CONNECT_SPEED_DOWNSTREAM}; + +static uint8_t EmptyResponse = 0x00U; + +/** + * @} + */ + +/** @defgroup USBD_CDC_RNDIS_Private_Variables + * @{ + */ + +static USBD_CDC_RNDIS_HandleTypeDef CDC_RNDIS_Instance; + +/* CDC_RNDIS interface class callbacks structure */ +USBD_ClassTypeDef USBD_CDC_RNDIS = + { + USBD_CDC_RNDIS_Init, + USBD_CDC_RNDIS_DeInit, + USBD_CDC_RNDIS_Setup, + NULL, /* EP0_TxSent, */ + USBD_CDC_RNDIS_EP0_RxReady, + USBD_CDC_RNDIS_DataIn, + USBD_CDC_RNDIS_DataOut, + NULL, + NULL, + NULL, + USBD_CDC_RNDIS_GetHSCfgDesc, + USBD_CDC_RNDIS_GetFSCfgDesc, + USBD_CDC_RNDIS_GetOtherSpeedCfgDesc, + USBD_CDC_RNDIS_GetDeviceQualifierDescriptor, +#if (USBD_SUPPORT_USER_STRING_DESC == 1U) + USBD_CDC_RNDIS_USRStringDescriptor, +#endif +}; + +/* USB CDC_RNDIS device Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_CDC_RNDIS_CfgHSDesc[CDC_RNDIS_CONFIG_DESC_SIZE] __ALIGN_END = + { + /* Configuration Descriptor */ + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + LOBYTE(CDC_RNDIS_CONFIG_DESC_SIZE), /* wTotalLength: Total size of the Config descriptor */ + HIBYTE(CDC_RNDIS_CONFIG_DESC_SIZE), + 0x02, /* bNumInterfaces: 2 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ +#if (USBD_SELF_POWERED == 1U) + 0xC0, /* bmAttributes: Bus Powered according to user configuration */ +#else + 0x80, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* MaxPower 100 mA */ + + /*---------------------------------------------------------------------------*/ + /* IAD descriptor */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_RNDIS_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0xE0, /* bFunctionClass (Wireless Controller) */ + 0x01, /* bFunctionSubClass */ + 0x03, /* bFunctionProtocol */ + _CDC_RNDIS_STR_DESC_IDX, /* iFunction */ + + /*---------------------------------------------------------------------------*/ + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ + _CDC_RNDIS_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoint used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass:Abstract Control Model */ + 0xFF, /* bInterfaceProtocol: Common AT commands */ + 0x00, /* iInterface: */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header functional descriptor */ + 0x10, /* bcdCDC: spec release number: 1.20 */ + 0x01, + + /* Call Management Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + _CDC_RNDIS_COM_ITF_NBR, /* bDataInterface: 1 */ + + /* ACM Functional Descriptor */ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x00, /* bmCapabilities */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union functional descriptor */ + _CDC_RNDIS_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_RNDIS_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* Notification Endpoint Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_RNDIS_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_RNDIS_CMD_PACKET_SIZE), /* wMaxPacketSize */ + HIBYTE(CDC_RNDIS_CMD_PACKET_SIZE), + CDC_RNDIS_HS_BINTERVAL, /* bInterval */ + + /*---------------------------------------------------------------------------*/ + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + _CDC_RNDIS_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass */ + 0x00, /* bInterfaceProtocol */ + 0x00, /* iInterface */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_RNDIS_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_RNDIS_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize */ + HIBYTE(CDC_RNDIS_DATA_HS_MAX_PACKET_SIZE), + 0x00, /* bInterval */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_RNDIS_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_RNDIS_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_RNDIS_DATA_HS_MAX_PACKET_SIZE), + 0x00 /* bInterval */ +}; + +/* USB CDC device Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_CDC_RNDIS_CfgFSDesc[CDC_RNDIS_CONFIG_DESC_SIZE] __ALIGN_END = + { + /* Configuration Descriptor */ + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + LOBYTE(CDC_RNDIS_CONFIG_DESC_SIZE), /* wTotalLength: Total size of the Config descriptor */ + HIBYTE(CDC_RNDIS_CONFIG_DESC_SIZE), + 0x02, /* bNumInterfaces: 2 interfaces */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ +#if (USBD_SELF_POWERED == 1U) + 0xC0, /* bmAttributes: Bus Powered according to user configuration */ +#else + 0x80, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* MaxPower 100 mA */ + + /*---------------------------------------------------------------------------*/ + /* IAD descriptor */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_RNDIS_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0xE0, /* bFunctionClass (Wireless Controller) */ + 0x01, /* bFunctionSubClass */ + 0x03, /* bFunctionProtocol */ + _CDC_RNDIS_STR_DESC_IDX, /* iFunction */ + + /*---------------------------------------------------------------------------*/ + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ + _CDC_RNDIS_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoint used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass:Abstract Control Model */ + 0xFF, /* bInterfaceProtocol: Common AT commands */ + 0x00, /* iInterface */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header functional descriptor */ + 0x10, /* bcdCDC: spec release number: 1.20 */ + 0x01, + + /* Call Management Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + _CDC_RNDIS_COM_ITF_NBR, /* bDataInterface: 1 */ + + /* ACM Functional Descriptor */ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x00, /* bmCapabilities */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union functional descriptor */ + _CDC_RNDIS_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_RNDIS_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* Notification Endpoint Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_RNDIS_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_RNDIS_CMD_PACKET_SIZE), /* wMaxPacketSize */ + HIBYTE(CDC_RNDIS_CMD_PACKET_SIZE), + CDC_RNDIS_FS_BINTERVAL, /* bInterval */ + + /*---------------------------------------------------------------------------*/ + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + _CDC_RNDIS_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass */ + 0x00, /* bInterfaceProtocol */ + 0x00, /* iInterface */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_RNDIS_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_RNDIS_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_RNDIS_DATA_FS_MAX_PACKET_SIZE), + 0x00, /* bInterval */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_RNDIS_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_RNDIS_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize */ + HIBYTE(CDC_RNDIS_DATA_FS_MAX_PACKET_SIZE), + 0x00 /* bInterval */ +}; + +__ALIGN_BEGIN static uint8_t USBD_CDC_RNDIS_OtherSpeedCfgDesc[] __ALIGN_END = + { + /* Configuration Descriptor */ + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + LOBYTE(CDC_RNDIS_CONFIG_DESC_SIZE), /* wTotalLength:no of returned bytes */ + HIBYTE(CDC_RNDIS_CONFIG_DESC_SIZE), + 0x02, /* bNumInterfaces: 2 interfaces */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x04, /* iConfiguration: Index of string descriptor describing the configuration */ +#if (USBD_SELF_POWERED == 1U) + 0xC0, /* bmAttributes: Bus Powered according to user configuration */ +#else + 0x80, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* MaxPower (mA) */ + + /*---------------------------------------------------------------------------*/ + /* IAD descriptor */ + 0x08, /* bLength */ + 0x0B, /* bDescriptorType */ + _CDC_RNDIS_CMD_ITF_NBR, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + 0xE0, /* bFunctionClass (Wireless Controller) */ + 0x01, /* bFunctionSubClass */ + 0x03, /* bFunctionProtocol */ + _CDC_RNDIS_STR_DESC_IDX, /* iFunction */ + + /*---------------------------------------------------------------------------*/ + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ + _CDC_RNDIS_CMD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoint used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass:Abstract Control Model */ + 0xFF, /* bInterfaceProtocol: Common AT commands */ + 0x00, /* iInterface */ + + /* Header Functional Descriptor */ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header functional descriptor */ + 0x10, /* bcdCDC: spec release number: 1.20 */ + 0x01, + + /* Call Management Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + _CDC_RNDIS_COM_ITF_NBR, /* bDataInterface: 1 */ + + /* ACM Functional Descriptor */ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x00, /* bmCapabilities */ + + /* Union Functional Descriptor */ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union functional descriptor */ + _CDC_RNDIS_CMD_ITF_NBR, /* bMasterInterface: Communication class interface */ + _CDC_RNDIS_COM_ITF_NBR, /* bSlaveInterface0: Data Class Interface */ + + /* Communication Endpoint Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_RNDIS_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_RNDIS_CMD_PACKET_SIZE), /* wMaxPacketSize */ + HIBYTE(CDC_RNDIS_CMD_PACKET_SIZE), + CDC_RNDIS_FS_BINTERVAL, /* bInterval */ + + /*---------------------------------------------------------------------------*/ + /* Data class interface descriptor */ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + _CDC_RNDIS_COM_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass */ + 0x00, /* bInterfaceProtocol */ + 0x00, /* iInterface */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_RNDIS_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + 0x40, /* wMaxPacketSize */ + 0x00, + 0x00, /* bInterval */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _CDC_RNDIS_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + 0x40, /* wMaxPacketSize */ + 0x00, + 0x00 /* bInterval */ +}; + +static const uint32_t CDC_RNDIS_SupportedOIDs[] = + { + OID_GEN_SUPPORTED_LIST, + OID_GEN_HARDWARE_STATUS, + OID_GEN_MEDIA_SUPPORTED, + OID_GEN_MEDIA_IN_USE, + OID_GEN_MAXIMUM_FRAME_SIZE, + OID_GEN_LINK_SPEED, + OID_GEN_TRANSMIT_BLOCK_SIZE, + OID_GEN_RECEIVE_BLOCK_SIZE, + OID_GEN_VENDOR_ID, + OID_GEN_VENDOR_DESCRIPTION, + OID_GEN_CURRENT_PACKET_FILTER, + OID_GEN_MAXIMUM_TOTAL_SIZE, + OID_GEN_MEDIA_CONNECT_STATUS, + OID_GEN_MAXIMUM_SEND_PACKETS, + OID_802_3_PERMANENT_ADDRESS, + OID_802_3_CURRENT_ADDRESS, + OID_802_3_MULTICAST_LIST, + OID_802_3_MAXIMUM_LIST_SIZE, + OID_802_3_RCV_ERROR_ALIGNMENT, + OID_802_3_XMIT_ONE_COLLISION, + OID_802_3_XMIT_MORE_COLLISIONS, +}; + +/** + * @} + */ + +/** @defgroup USBD_CDC_RNDIS_Private_Functions + * @{ + */ + +/** + * @brief USBD_CDC_RNDIS_Init + * Initialize the CDC CDC_RNDIS interface + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_CDC_RNDIS_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(cfgidx); + USBD_CDC_RNDIS_HandleTypeDef *hcdc; + + hcdc = &CDC_RNDIS_Instance; + + if (hcdc == NULL) + { + pdev->pClassData_CDC_RNDIS = NULL; + return (uint8_t)USBD_EMEM; + } + + pdev->pClassData_CDC_RNDIS = (void *)hcdc; + + if (pdev->dev_speed == USBD_SPEED_HIGH) + { + /* Open EP IN */ + (void)USBD_LL_OpenEP(pdev, CDC_RNDIS_IN_EP, USBD_EP_TYPE_BULK, + CDC_RNDIS_DATA_HS_IN_PACKET_SIZE); + + pdev->ep_in[CDC_RNDIS_IN_EP & 0xFU].is_used = 1U; + + /* Open EP OUT */ + (void)USBD_LL_OpenEP(pdev, CDC_RNDIS_OUT_EP, USBD_EP_TYPE_BULK, + CDC_RNDIS_DATA_HS_OUT_PACKET_SIZE); + + pdev->ep_out[CDC_RNDIS_OUT_EP & 0xFU].is_used = 1U; + + /* Set bInterval for CDC RNDIS CMD Endpoint */ + pdev->ep_in[CDC_RNDIS_CMD_EP & 0xFU].bInterval = CDC_RNDIS_HS_BINTERVAL; + } + else + { + /* Open EP IN */ + (void)USBD_LL_OpenEP(pdev, CDC_RNDIS_IN_EP, USBD_EP_TYPE_BULK, + CDC_RNDIS_DATA_FS_IN_PACKET_SIZE); + + pdev->ep_in[CDC_RNDIS_IN_EP & 0xFU].is_used = 1U; + + /* Open EP OUT */ + (void)USBD_LL_OpenEP(pdev, CDC_RNDIS_OUT_EP, USBD_EP_TYPE_BULK, + CDC_RNDIS_DATA_FS_OUT_PACKET_SIZE); + + pdev->ep_out[CDC_RNDIS_OUT_EP & 0xFU].is_used = 1U; + + /* Set bInterval for CDC RNDIS CMD Endpoint */ + pdev->ep_in[CDC_RNDIS_CMD_EP & 0xFU].bInterval = CDC_RNDIS_FS_BINTERVAL; + } + + /* Open Command IN EP */ + (void)USBD_LL_OpenEP(pdev, CDC_RNDIS_CMD_EP, USBD_EP_TYPE_INTR, CDC_RNDIS_CMD_PACKET_SIZE); + pdev->ep_in[CDC_RNDIS_CMD_EP & 0xFU].is_used = 1U; + + /* Init physical Interface components */ + ((USBD_CDC_RNDIS_ItfTypeDef *)pdev->pUserData_CDC_RNDIS)->Init(); + + /* Init the CDC_RNDIS state */ + hcdc->State = CDC_RNDIS_STATE_BUS_INITIALIZED; + + /* Init Xfer states */ + hcdc->TxState = 0U; + hcdc->RxState = 0U; + hcdc->RxLength = 0U; + hcdc->TxLength = 0U; + hcdc->LinkStatus = 0U; + hcdc->NotificationStatus = 0U; + hcdc->MaxPcktLen = (pdev->dev_speed == USBD_SPEED_HIGH) ? CDC_RNDIS_DATA_HS_MAX_PACKET_SIZE : CDC_RNDIS_DATA_FS_MAX_PACKET_SIZE; + + /* Prepare Out endpoint to receive next packet */ + (void)USBD_LL_PrepareReceive(pdev, CDC_RNDIS_OUT_EP, + hcdc->RxBuffer, hcdc->MaxPcktLen); + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_RNDIS_DeInit + * DeInitialize the CDC layer + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_CDC_RNDIS_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(cfgidx); + + /* Close EP IN */ + (void)USBD_LL_CloseEP(pdev, CDC_RNDIS_IN_EP); + pdev->ep_in[CDC_RNDIS_IN_EP & 0xFU].is_used = 0U; + + /* Close EP OUT */ + (void)USBD_LL_CloseEP(pdev, CDC_RNDIS_OUT_EP); + pdev->ep_out[CDC_RNDIS_OUT_EP & 0xFU].is_used = 0U; + + /* Close Command IN EP */ + (void)USBD_LL_CloseEP(pdev, CDC_RNDIS_CMD_EP); + pdev->ep_in[CDC_RNDIS_CMD_EP & 0xFU].is_used = 0U; + pdev->ep_in[CDC_RNDIS_CMD_EP & 0xFU].bInterval = 0U; + + /* DeInit physical Interface components */ + if (pdev->pClassData_CDC_RNDIS != NULL) + { + ((USBD_CDC_RNDIS_ItfTypeDef *)pdev->pUserData_CDC_RNDIS)->DeInit(); +#if (0) + USBD_free(pdev->pClassData_CDC_RNDIS); +#endif + pdev->pClassData_CDC_RNDIS = NULL; + } + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_RNDIS_Setup + * Handle the CDC specific requests + * @param pdev: instance + * @param req: usb requests + * @retval status + */ +static uint8_t USBD_CDC_RNDIS_Setup(USBD_HandleTypeDef *pdev, + USBD_SetupReqTypedef *req) +{ + USBD_CDC_RNDIS_HandleTypeDef *hcdc = (USBD_CDC_RNDIS_HandleTypeDef *)pdev->pClassData_CDC_RNDIS; + USBD_CDC_RNDIS_CtrlMsgTypeDef *Msg = (USBD_CDC_RNDIS_CtrlMsgTypeDef *)(void *)hcdc->data; + uint8_t ifalt = 0U; + uint16_t status_info = 0U; + USBD_StatusTypeDef ret = USBD_OK; + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + switch (req->bmRequest & USB_REQ_TYPE_MASK) + { + case USB_REQ_TYPE_CLASS: + if (req->wLength != 0U) + { + /* Control Request Data from Device to Host, send data prepared by device */ + if ((req->bmRequest & 0x80U) != 0U) + { + /* Update opcode and length */ + hcdc->CmdOpCode = req->bRequest; + hcdc->CmdLength = (uint8_t)req->wLength; + + if (hcdc->CmdOpCode == CDC_RNDIS_GET_ENCAPSULATED_RESPONSE) + { + /* Data of Response Message has already been prepared by USBD_CDC_RNDIS_MsgParsing. + Just check that length is corresponding to right expected value */ + if (req->wLength != Msg->MsgLength) + { + } + } + + /* Allow application layer to pre-process data or add own processing before sending response */ + ((USBD_CDC_RNDIS_ItfTypeDef *)pdev->pUserData_CDC_RNDIS)->Control(req->bRequest, (uint8_t *)hcdc->data, req->wLength); + /* Check if Response is ready */ + if (hcdc->ResponseRdy != 0U) + { + /* Clear Response Ready flag */ + hcdc->ResponseRdy = 0U; + + /* Send data on control endpoint */ + (void)USBD_CtlSendData(pdev, (uint8_t *)hcdc->data, + MIN(CDC_RNDIS_MAX_DATA_SZE, Msg->MsgLength)); + } + else + { + /* CDC_RNDIS Specification says: If for some reason the device receives a GET ENCAPSULATED RESPONSE + and is unable to respond with a valid data on the Control endpoint, + then it should return a one-byte packet set to 0x00, rather than + stalling the Control endpoint */ + (void)USBD_CtlSendData(pdev, &EmptyResponse, 1U); + } + } + /* Control Request Data from Host to Device: Prepare reception of control data stage */ + else + { + hcdc->CmdOpCode = req->bRequest; + hcdc->CmdLength = (uint8_t)MIN(CDC_RNDIS_CMD_PACKET_SIZE, req->wLength); + + (void)USBD_CtlPrepareRx(pdev, (uint8_t *)hcdc->data, hcdc->CmdLength); + } + } + /* No Data control request: there is no such request for CDC_RNDIS protocol, + so let application layer manage this case */ + else + { + ((USBD_CDC_RNDIS_ItfTypeDef *)pdev->pUserData_CDC_RNDIS)->Control(req->bRequest, (uint8_t *)req, 0U); + } + break; + + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) + { + case USB_REQ_GET_STATUS: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_GET_INTERFACE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, &ifalt, 1U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_SET_INTERFACE: + if (pdev->dev_state != USBD_STATE_CONFIGURED) + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_CLEAR_FEATURE: + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + + return (uint8_t)ret; +} + +/** + * @brief USBD_CDC_RNDIS_DataIn + * Data sent on non-control IN endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +static uint8_t USBD_CDC_RNDIS_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + USBD_CDC_RNDIS_HandleTypeDef *hcdc; + PCD_HandleTypeDef *hpcd = pdev->pData; + + if (pdev->pClassData_CDC_RNDIS == NULL) + { + return (uint8_t)USBD_FAIL; + } + + hcdc = (USBD_CDC_RNDIS_HandleTypeDef *)pdev->pClassData_CDC_RNDIS; + + if (epnum == (CDC_RNDIS_IN_EP & 0x7FU)) + { + if ((pdev->ep_in[epnum & 0xFU].total_length > 0U) && + ((pdev->ep_in[epnum & 0xFU].total_length % hpcd->IN_ep[epnum & 0xFU].maxpacket) == 0U)) + { + /* Update the packet total length */ + pdev->ep_in[epnum & 0xFU].total_length = 0U; + + /* Send ZLP */ + (void)USBD_LL_Transmit(pdev, epnum, NULL, 0U); + } + else + { + hcdc->TxState = 0U; + + if (((USBD_CDC_RNDIS_ItfTypeDef *)pdev->pUserData_CDC_RNDIS)->TransmitCplt != NULL) + { + ((USBD_CDC_RNDIS_ItfTypeDef *)pdev->pUserData_CDC_RNDIS)->TransmitCplt(hcdc->TxBuffer, &hcdc->TxLength, epnum); + } + } + } + else if (epnum == (CDC_RNDIS_CMD_EP & 0x7FU)) + { + if (hcdc->NotificationStatus != 0U) + { + (void)USBD_CDC_RNDIS_SendNotification(pdev, RNDIS_CONNECTION_SPEED_CHANGE, + 0U, (uint8_t *)ConnSpeedTab); + + hcdc->NotificationStatus = 0U; + } + } + else + { + return (uint8_t)USBD_FAIL; + } + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_RNDIS_DataOut + * Data received on non-control Out endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +static uint8_t USBD_CDC_RNDIS_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + USBD_CDC_RNDIS_HandleTypeDef *hcdc; + uint32_t CurrPcktLen; + + if (pdev->pClassData_CDC_RNDIS == NULL) + { + return (uint8_t)USBD_FAIL; + } + + hcdc = (USBD_CDC_RNDIS_HandleTypeDef *)pdev->pClassData_CDC_RNDIS; + + if (epnum == CDC_RNDIS_OUT_EP) + { + /* Get the received data length */ + CurrPcktLen = USBD_LL_GetRxDataSize(pdev, epnum); + + /* Increment the frame length */ + hcdc->RxLength += CurrPcktLen; + + /* If the buffer size is less than max packet size: it is the last packet in current frame */ + if ((CurrPcktLen < hcdc->MaxPcktLen) || + (hcdc->RxLength >= (CDC_RNDIS_ETH_MAX_SEGSZE + sizeof(USBD_CDC_RNDIS_PacketMsgTypeDef)))) + { + /* USB data will be immediately processed, this allow next USB traffic being + NAKed till the end of the application Xfer */ + + /* Call data packet message parsing and processing function */ + (void)USBD_CDC_RNDIS_ProcessPacketMsg(pdev, (USBD_CDC_RNDIS_PacketMsgTypeDef *)(void *)hcdc->RxBuffer); + } + else + { + /* Prepare Out endpoint to receive next packet in current/new frame */ + (void)USBD_LL_PrepareReceive(pdev, CDC_RNDIS_OUT_EP, + (uint8_t *)(hcdc->RxBuffer + hcdc->RxLength), + hcdc->MaxPcktLen); + } + } + else + { + return (uint8_t)USBD_FAIL; + } + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_RNDIS_EP0_RxReady + * Handle EP0 Rx Ready event + * @param pdev: device instance + * @retval status + */ +static uint8_t USBD_CDC_RNDIS_EP0_RxReady(USBD_HandleTypeDef *pdev) +{ + USBD_CDC_RNDIS_HandleTypeDef *hcdc = (USBD_CDC_RNDIS_HandleTypeDef *)pdev->pClassData_CDC_RNDIS; + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + if ((pdev->pUserData_CDC_RNDIS != NULL) && (hcdc->CmdOpCode != 0xFFU)) + { + /* Check if the received command is SendEncapsulated command */ + if (hcdc->CmdOpCode == CDC_RNDIS_SEND_ENCAPSULATED_COMMAND) + { + /* Process Received CDC_RNDIS Control Message */ + (void)USBD_CDC_RNDIS_MsgParsing(pdev, (uint8_t *)(hcdc->data)); + + /* Reset the command opcode for next processing */ + hcdc->CmdOpCode = 0xFFU; + } + else + { + /* Reset the command opcode for next processing */ + hcdc->CmdOpCode = 0xFFU; + + /* Ignore the command and return fail */ + return (uint8_t)USBD_FAIL; + } + } + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_RNDIS_GetFSCfgDesc + * Return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CDC_RNDIS_GetFSCfgDesc(uint16_t *length) +{ + *length = (uint16_t)(sizeof(USBD_CDC_RNDIS_CfgFSDesc)); + + return USBD_CDC_RNDIS_CfgFSDesc; +} + +/** + * @brief USBD_CDC_RNDIS_GetHSCfgDesc + * Return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CDC_RNDIS_GetHSCfgDesc(uint16_t *length) +{ + *length = (uint16_t)(sizeof(USBD_CDC_RNDIS_CfgHSDesc)); + + return USBD_CDC_RNDIS_CfgHSDesc; +} + +/** + * @brief USBD_CDC_RNDIS_GetOtherSpeedCfgDesc + * Return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CDC_RNDIS_GetOtherSpeedCfgDesc(uint16_t *length) +{ + *length = (uint16_t)(sizeof(USBD_CDC_RNDIS_OtherSpeedCfgDesc)); + + return USBD_CDC_RNDIS_OtherSpeedCfgDesc; +} + +/** + * @brief DeviceQualifierDescriptor + * return Device Qualifier descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +uint8_t *USBD_CDC_RNDIS_GetDeviceQualifierDescriptor(uint16_t *length) +{ + *length = (uint16_t)(sizeof(USBD_CDC_RNDIS_DeviceQualifierDesc)); + + return USBD_CDC_RNDIS_DeviceQualifierDesc; +} + +/** + * @brief USBD_CDC_RNDIS_RegisterInterface + * @param pdev: device instance + * @param fops: CD Interface callback + * @retval status + */ +uint8_t USBD_CDC_RNDIS_RegisterInterface(USBD_HandleTypeDef *pdev, + USBD_CDC_RNDIS_ItfTypeDef *fops) +{ + if (fops == NULL) + { + return (uint8_t)USBD_FAIL; + } + + pdev->pUserData_CDC_RNDIS = fops; + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_RNDIS_USRStringDescriptor + * Manages the transfer of user string descriptors. + * @param speed : current device speed + * @param index: descriptor index + * @param length : pointer data length + * @retval pointer to the descriptor table or NULL if the descriptor is not supported. + */ +#if (USBD_SUPPORT_USER_STRING_DESC == 1U) +static uint8_t *USBD_CDC_RNDIS_USRStringDescriptor(USBD_HandleTypeDef *pdev, uint8_t index, uint16_t *length) +{ + static uint8_t USBD_StrDesc[255]; + + /* Check if the requested string interface is supported */ + if (index == CDC_RNDIS_MAC_STRING_INDEX) + { + USBD_GetString((uint8_t *)((USBD_CDC_RNDIS_ItfTypeDef *)pdev->pUserData_CDC_RNDIS)->pStrDesc, USBD_StrDesc, length); + return USBD_StrDesc; + } + /* Not supported Interface Descriptor index */ + else + { + return NULL; + } +} +#endif /* USBD_SUPPORT_USER_STRING_DESC */ + +/** + * @brief USBD_CDC_RNDIS_SetTxBuffer + * @param pdev: device instance + * @param pbuff: Tx Buffer + * @retval status + */ +uint8_t USBD_CDC_RNDIS_SetTxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff, uint32_t length) +{ + USBD_CDC_RNDIS_HandleTypeDef *hcdc = (USBD_CDC_RNDIS_HandleTypeDef *)pdev->pClassData_CDC_RNDIS; + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + hcdc->TxBuffer = pbuff; + hcdc->TxLength = length; + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_RNDIS_SetRxBuffer + * @param pdev: device instance + * @param pbuff: Rx Buffer + * @retval status + */ +uint8_t USBD_CDC_RNDIS_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff) +{ + USBD_CDC_RNDIS_HandleTypeDef *hcdc = (USBD_CDC_RNDIS_HandleTypeDef *)pdev->pClassData_CDC_RNDIS; + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + hcdc->RxBuffer = pbuff; + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_RNDIS_TransmitPacket + * Transmit packet on IN endpoint + * @param pdev: device instance + * @retval status + */ +uint8_t USBD_CDC_RNDIS_TransmitPacket(USBD_HandleTypeDef *pdev) +{ + USBD_CDC_RNDIS_HandleTypeDef *hcdc; + USBD_CDC_RNDIS_PacketMsgTypeDef *PacketMsg; + USBD_StatusTypeDef ret = USBD_BUSY; + + if (pdev->pClassData_CDC_RNDIS == NULL) + { + return (uint8_t)USBD_FAIL; + } + + hcdc = (USBD_CDC_RNDIS_HandleTypeDef *)pdev->pClassData_CDC_RNDIS; + PacketMsg = (USBD_CDC_RNDIS_PacketMsgTypeDef *)(void *)hcdc->TxBuffer; + + if (hcdc->TxState == 0U) + { + /* Tx Transfer in progress */ + hcdc->TxState = 1U; + + /* Format the packet information */ + PacketMsg->MsgType = CDC_RNDIS_PACKET_MSG_ID; + PacketMsg->MsgLength = hcdc->TxLength; + PacketMsg->DataOffset = sizeof(USBD_CDC_RNDIS_PacketMsgTypeDef) - CDC_RNDIS_PCKTMSG_DATAOFFSET_OFFSET; + PacketMsg->DataLength = hcdc->TxLength - sizeof(USBD_CDC_RNDIS_PacketMsgTypeDef); + PacketMsg->OOBDataOffset = 0U; + PacketMsg->OOBDataLength = 0U; + PacketMsg->NumOOBDataElements = 0U; + PacketMsg->PerPacketInfoOffset = 0U; + PacketMsg->PerPacketInfoLength = 0U; + PacketMsg->VcHandle = 0U; + PacketMsg->Reserved = 0U; + + /* Update the packet total length */ + pdev->ep_in[CDC_RNDIS_IN_EP & 0xFU].total_length = hcdc->TxLength; + + /* Transmit next packet */ + (void)USBD_LL_Transmit(pdev, CDC_RNDIS_IN_EP, hcdc->TxBuffer, hcdc->TxLength); + + ret = USBD_OK; + } + + return (uint8_t)ret; +} + +/** + * @brief USBD_CDC_RNDIS_ReceivePacket + * prepare OUT Endpoint for reception + * @param pdev: device instance + * @retval status + */ +uint8_t USBD_CDC_RNDIS_ReceivePacket(USBD_HandleTypeDef *pdev) +{ + USBD_CDC_RNDIS_HandleTypeDef *hcdc; + + if (pdev->pClassData_CDC_RNDIS == NULL) + { + return (uint8_t)USBD_FAIL; + } + + hcdc = (USBD_CDC_RNDIS_HandleTypeDef *)pdev->pClassData_CDC_RNDIS; + + /* Prepare Out endpoint to receive next packet */ + (void)USBD_LL_PrepareReceive(pdev, CDC_RNDIS_OUT_EP, + hcdc->RxBuffer, hcdc->MaxPcktLen); + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_RNDIS_SendNotification + * Transmit Notification packet on CMD IN interrupt endpoint + * @param pdev: device instance + * Notif: value of the notification type (from CDC_RNDIS_Notification_TypeDef enumeration list) + * bVal: value of the notification switch (ie. 0x00 or 0x01 for Network Connection notification) + * pData: pointer to data buffer (ie. upstream and downstream connection speed values) + * @retval status + */ +uint8_t USBD_CDC_RNDIS_SendNotification(USBD_HandleTypeDef *pdev, + USBD_CDC_RNDIS_NotifCodeTypeDef Notif, + uint16_t bVal, uint8_t *pData) +{ + uint32_t Idx; + uint16_t ReqSize = 0U; + USBD_CDC_RNDIS_HandleTypeDef *hcdc = (USBD_CDC_RNDIS_HandleTypeDef *)pdev->pClassData_CDC_RNDIS; + USBD_StatusTypeDef ret = USBD_OK; + + UNUSED(bVal); + UNUSED(pData); + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + /* Initialize the request fields */ + (hcdc->Req).bmRequest = CDC_RNDIS_BMREQUEST_TYPE_RNDIS; + (hcdc->Req).bRequest = (uint8_t)Notif; + + switch (Notif) + { + case RNDIS_RESPONSE_AVAILABLE: + (hcdc->Req).wValue = 0U; + (hcdc->Req).wIndex = CDC_RNDIS_CMD_ITF_NBR; + (hcdc->Req).wLength = 0U; + + for (Idx = 0U; Idx < 8U; Idx++) + { + (hcdc->Req).data[Idx] = 0U; + } + + ReqSize = 8U; + break; + + default: + ret = USBD_FAIL; + break; + } + + /* Transmit notification packet */ + if (ReqSize != 0U) + { + (void)USBD_LL_Transmit(pdev, CDC_RNDIS_CMD_EP, (uint8_t *)&(hcdc->Req), ReqSize); + } + + return (uint8_t)ret; +} + +/* ----------------------------- CDC_RNDIS Messages processing functions ----------------------- */ +/** + * @brief USBD_CDC_RNDIS_MsgParsing + * Parse received message and process it depending on its nature. + * @param pdev: USB Device Handle pointer + * @param RxBuff: Pointer to the message data extracted from SendEncapsulated command + * @retval status + */ +static uint8_t USBD_CDC_RNDIS_MsgParsing(USBD_HandleTypeDef *pdev, uint8_t *RxBuff) +{ + USBD_CDC_RNDIS_CtrlMsgTypeDef *Msg = (USBD_CDC_RNDIS_CtrlMsgTypeDef *)(void *)RxBuff; + static uint8_t ret = (uint8_t)USBD_OK; + + /* Check message type */ + switch (Msg->MsgType) + { + /* CDC_RNDIS Initialize message */ + case CDC_RNDIS_INITIALIZE_MSG_ID: + ret = USBD_CDC_RNDIS_ProcessInitMsg(pdev, (USBD_CDC_RNDIS_InitMsgTypeDef *)(void *)Msg); + break; + + /* CDC_RNDIS Halt message */ + case CDC_RNDIS_HALT_MSG_ID: + ret = USBD_CDC_RNDIS_ProcessHaltMsg(pdev, (USBD_CDC_RNDIS_HaltMsgTypeDef *)(void *)Msg); + break; + + /* CDC_RNDIS Query message */ + case CDC_RNDIS_QUERY_MSG_ID: + ret = USBD_CDC_RNDIS_ProcessQueryMsg(pdev, (USBD_CDC_RNDIS_QueryMsgTypeDef *)(void *)Msg); + break; + + /* CDC_RNDIS Set message */ + case CDC_RNDIS_SET_MSG_ID: + ret = USBD_CDC_RNDIS_ProcessSetMsg(pdev, (USBD_CDC_RNDIS_SetMsgTypeDef *)(void *)Msg); + break; + + /* CDC_RNDIS Reset message */ + case CDC_RNDIS_RESET_MSG_ID: + ret = USBD_CDC_RNDIS_ProcessResetMsg(pdev, (USBD_CDC_RNDIS_ResetMsgTypeDef *)(void *)Msg); + break; + + /* CDC_RNDIS Keep-Alive message */ + case CDC_RNDIS_KEEPALIVE_MSG_ID: + ret = USBD_CDC_RNDIS_ProcessKeepAliveMsg(pdev, (USBD_CDC_RNDIS_KpAliveMsgTypeDef *)(void *)Msg); + break; + + /* CDC_RNDIS unsupported message */ + default: + ret = USBD_CDC_RNDIS_ProcessUnsupportedMsg(pdev, (USBD_CDC_RNDIS_CtrlMsgTypeDef *)(void *)Msg); + break; + } + + return ret; +} + +/** + * @brief USBD_CDC_RNDIS_ProcessInitMsg + * Parse, extract data and check correctness of CDC_RNDIS INIT_MSG command. + * @param pdev: USB Device Handle pointer + * @param Msg: Pointer to the message data extracted from SendEncapsulated command + * @retval status + */ +static uint8_t USBD_CDC_RNDIS_ProcessInitMsg(USBD_HandleTypeDef *pdev, + USBD_CDC_RNDIS_InitMsgTypeDef *Msg) +{ + /* Get the CDC_RNDIS handle pointer */ + USBD_CDC_RNDIS_HandleTypeDef *hcdc = (USBD_CDC_RNDIS_HandleTypeDef *)pdev->pClassData_CDC_RNDIS; + + /* Get and format the Msg input */ + USBD_CDC_RNDIS_InitMsgTypeDef *InitMessage = (USBD_CDC_RNDIS_InitMsgTypeDef *)Msg; + + /* Use same Msg input buffer as response buffer */ + USBD_CDC_RNDIS_InitCpltMsgTypeDef *InitResponse = (USBD_CDC_RNDIS_InitCpltMsgTypeDef *)(void *)Msg; + + /* Store the Message Request ID */ + uint32_t ReqId = InitMessage->ReqId; + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + /* Check correctness of the message (MsgType already checked by entry to this function) */ + if ((InitMessage->MsgLength != sizeof(USBD_CDC_RNDIS_InitMsgTypeDef)) || + (InitMessage->MajorVersion < CDC_RNDIS_VERSION_MAJOR)) + { + InitResponse->Status = CDC_RNDIS_STATUS_FAILURE; + } + else + { + InitResponse->Status = CDC_RNDIS_STATUS_SUCCESS; + } + + /* Setup the response buffer content */ + InitResponse->MsgType = CDC_RNDIS_INITIALIZE_CMPLT_ID; + InitResponse->MsgLength = sizeof(USBD_CDC_RNDIS_InitCpltMsgTypeDef); + InitResponse->ReqId = ReqId; + InitResponse->MajorVersion = CDC_RNDIS_VERSION_MAJOR; + InitResponse->MinorVersion = CDC_RNDIS_VERSION_MINOR; + InitResponse->DeviceFlags = CDC_RNDIS_DF_CONNECTIONLESS; + InitResponse->Medium = CDC_RNDIS_MEDIUM_802_3; + InitResponse->MaxPacketsPerTransfer = 1U; + InitResponse->MaxTransferSize = (sizeof(USBD_CDC_RNDIS_PacketMsgTypeDef) + CDC_RNDIS_ETH_FRAME_SIZE_MAX); + InitResponse->PacketAlignmentFactor = 2U; /* Not needed as single packet by transfer set */ + InitResponse->AFListOffset = 0U; /* Reserved for connection-oriented devices. Set value to zero. */ + InitResponse->AFListSize = 0U; /* Reserved for connection-oriented devices. Set value to zero. */ + + /* Set CDC_RNDIS state to INITIALIZED */ + hcdc->State = CDC_RNDIS_STATE_INITIALIZED; + + /* Set Response Ready field in order to send response during next control request */ + hcdc->ResponseRdy = 1U; + + /* Send Notification on Interrupt EP to inform Host that response is ready */ + (void)USBD_CDC_RNDIS_SendNotification(pdev, RNDIS_RESPONSE_AVAILABLE, 0U, NULL); + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_RNDIS_ProcessHaltMsg + * Parse, extract data and check correctness of CDC_RNDIS Halt command. + * @param pdev: USB Device Handle pointer + * @param Msg: Pointer to the message data extracted from SendEncapsulated command + * @retval status + */ +static uint8_t USBD_CDC_RNDIS_ProcessHaltMsg(USBD_HandleTypeDef *pdev, + USBD_CDC_RNDIS_HaltMsgTypeDef *Msg) +{ + /* Get the CDC_RNDIS handle pointer */ + USBD_CDC_RNDIS_HandleTypeDef *hcdc = (USBD_CDC_RNDIS_HandleTypeDef *)pdev->pClassData_CDC_RNDIS; + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + /* Set CDC_RNDIS state to INITIALIZED */ + hcdc->State = CDC_RNDIS_STATE_UNINITIALIZED; + + /* No response required for this message, so no notification (RESPONSE_AVAILABLE) is sent */ + + UNUSED(Msg); + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_RNDIS_ProcessKeepAliveMsg + * Parse, extract data and check correctness of CDC_RNDIS KeepAlive command. + * @param pdev: USB Device Handle pointer + * @param Msg: Pointer to the message data extracted from SendEncapsulated command + * @retval status + */ +static uint8_t USBD_CDC_RNDIS_ProcessKeepAliveMsg(USBD_HandleTypeDef *pdev, + USBD_CDC_RNDIS_KpAliveMsgTypeDef *Msg) +{ + /* Get the CDC_RNDIS handle pointer */ + USBD_CDC_RNDIS_HandleTypeDef *hcdc = (USBD_CDC_RNDIS_HandleTypeDef *)pdev->pClassData_CDC_RNDIS; + + /* Use same Msg input buffer as response buffer */ + USBD_CDC_RNDIS_KpAliveCpltMsgTypeDef *InitResponse = (USBD_CDC_RNDIS_KpAliveCpltMsgTypeDef *)(void *)Msg; + + /* Store the Message Request ID */ + uint32_t ReqId = Msg->ReqId; + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + /* Check correctness of the message (MsgType already checked by entry to this function) */ + if (Msg->MsgLength != sizeof(USBD_CDC_RNDIS_KpAliveMsgTypeDef)) + { + InitResponse->Status = CDC_RNDIS_STATUS_FAILURE; + } + else + { + InitResponse->Status = CDC_RNDIS_STATUS_SUCCESS; + } + + /* Setup the response buffer content */ + InitResponse->MsgType = CDC_RNDIS_KEEPALIVE_CMPLT_ID; + InitResponse->MsgLength = sizeof(USBD_CDC_RNDIS_KpAliveCpltMsgTypeDef); + InitResponse->ReqId = ReqId; + InitResponse->Status = CDC_RNDIS_STATUS_SUCCESS; + + /* Set Response Ready field in order to send response during next control request */ + hcdc->ResponseRdy = 1U; + + /* Send Notification on Interrupt EP to inform Host that response is ready */ + (void)USBD_CDC_RNDIS_SendNotification(pdev, RNDIS_RESPONSE_AVAILABLE, 0U, NULL); + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_RNDIS_ProcessQueryMsg + * Parse, extract data and check correctness of CDC_RNDIS Query command. + * @param pdev: USB Device Handle pointer + * @param Msg: Pointer to the message data extracted from SendEncapsulated command + * @retval status + */ +static uint8_t USBD_CDC_RNDIS_ProcessQueryMsg(USBD_HandleTypeDef *pdev, + USBD_CDC_RNDIS_QueryMsgTypeDef *Msg) +{ + /* Get the CDC_RNDIS handle pointer */ + USBD_CDC_RNDIS_HandleTypeDef *hcdc = (USBD_CDC_RNDIS_HandleTypeDef *)pdev->pClassData_CDC_RNDIS; + + /* Use same Msg input buffer as response buffer */ + USBD_CDC_RNDIS_QueryCpltMsgTypeDef *QueryResponse = (USBD_CDC_RNDIS_QueryCpltMsgTypeDef *)(void *)Msg; + + /* Store the Message Request ID */ + uint32_t ReqId = Msg->RequestId; + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + /* Process the OID depending on its code */ + switch (Msg->Oid) + { + case OID_GEN_SUPPORTED_LIST: + QueryResponse->InfoBufLength = sizeof(CDC_RNDIS_SupportedOIDs); + (void)USBD_memcpy(QueryResponse->InfoBuf, CDC_RNDIS_SupportedOIDs, + sizeof(CDC_RNDIS_SupportedOIDs)); + + QueryResponse->Status = CDC_RNDIS_STATUS_SUCCESS; + break; + + case OID_GEN_HARDWARE_STATUS: + QueryResponse->InfoBufLength = sizeof(uint32_t); + QueryResponse->InfoBuf[0] = CDC_RNDIS_HW_STS_READY; + QueryResponse->Status = CDC_RNDIS_STATUS_SUCCESS; + break; + + case OID_GEN_MEDIA_SUPPORTED: + case OID_GEN_MEDIA_IN_USE: + QueryResponse->InfoBufLength = sizeof(uint32_t); + QueryResponse->InfoBuf[0] = CDC_RNDIS_MEDIUM_802_3; + QueryResponse->Status = CDC_RNDIS_STATUS_SUCCESS; + break; + + case OID_GEN_VENDOR_ID: + QueryResponse->InfoBufLength = sizeof(uint32_t); + QueryResponse->InfoBuf[0] = USBD_CDC_RNDIS_VID; + QueryResponse->Status = CDC_RNDIS_STATUS_SUCCESS; + break; + + case OID_GEN_MAXIMUM_FRAME_SIZE: + case OID_GEN_TRANSMIT_BLOCK_SIZE: + case OID_GEN_RECEIVE_BLOCK_SIZE: + QueryResponse->InfoBufLength = sizeof(uint32_t); + QueryResponse->InfoBuf[0] = CDC_RNDIS_ETH_FRAME_SIZE_MAX; + QueryResponse->Status = CDC_RNDIS_STATUS_SUCCESS; + break; + + case OID_GEN_VENDOR_DESCRIPTION: + QueryResponse->InfoBufLength = (strlen(USBD_CDC_RNDIS_VENDOR_DESC) + 1U); + (void)USBD_memcpy(QueryResponse->InfoBuf, USBD_CDC_RNDIS_VENDOR_DESC, + strlen(USBD_CDC_RNDIS_VENDOR_DESC)); + + QueryResponse->Status = CDC_RNDIS_STATUS_SUCCESS; + break; + + case OID_GEN_MEDIA_CONNECT_STATUS: + QueryResponse->InfoBufLength = sizeof(uint32_t); + QueryResponse->InfoBuf[0] = CDC_RNDIS_MEDIA_STATE_CONNECTED; + QueryResponse->Status = CDC_RNDIS_STATUS_SUCCESS; + break; + + case OID_GEN_MAXIMUM_SEND_PACKETS: + QueryResponse->InfoBufLength = sizeof(uint32_t); + QueryResponse->InfoBuf[0] = 1U; + QueryResponse->Status = CDC_RNDIS_STATUS_SUCCESS; + break; + + case OID_GEN_LINK_SPEED: + QueryResponse->InfoBufLength = sizeof(uint32_t); + QueryResponse->InfoBuf[0] = USBD_CDC_RNDIS_LINK_SPEED; + QueryResponse->Status = CDC_RNDIS_STATUS_SUCCESS; + break; + + case OID_802_3_PERMANENT_ADDRESS: + case OID_802_3_CURRENT_ADDRESS: + QueryResponse->InfoBufLength = 6U; + (void)USBD_memcpy(QueryResponse->InfoBuf, MAC_StrDesc, 6); + QueryResponse->Status = CDC_RNDIS_STATUS_SUCCESS; + break; + + case OID_802_3_MAXIMUM_LIST_SIZE: + QueryResponse->InfoBufLength = sizeof(uint32_t); + QueryResponse->InfoBuf[0] = 1U; /* Only one multicast address supported */ + QueryResponse->Status = CDC_RNDIS_STATUS_SUCCESS; + break; + + case OID_GEN_CURRENT_PACKET_FILTER: + QueryResponse->InfoBufLength = sizeof(uint32_t); + QueryResponse->InfoBuf[0] = 0xFFFFFFU; /* USBD_CDC_RNDIS_DEVICE.packetFilter; */ + QueryResponse->Status = CDC_RNDIS_STATUS_SUCCESS; + break; + + case OID_802_3_RCV_ERROR_ALIGNMENT: + case OID_802_3_XMIT_ONE_COLLISION: + case OID_802_3_XMIT_MORE_COLLISIONS: + QueryResponse->InfoBufLength = sizeof(uint32_t); + QueryResponse->InfoBuf[0] = 0U; /* Unused OIDs, return zero */ + QueryResponse->Status = CDC_RNDIS_STATUS_SUCCESS; + break; + + case OID_GEN_MAXIMUM_TOTAL_SIZE: + QueryResponse->InfoBufLength = sizeof(uint32_t); + /* Indicate maximum overall buffer (Ethernet frame and CDC_RNDIS header) the adapter can handle */ + QueryResponse->InfoBuf[0] = (CDC_RNDIS_MESSAGE_BUFFER_SIZE + CDC_RNDIS_ETH_FRAME_SIZE_MAX); + QueryResponse->Status = CDC_RNDIS_STATUS_SUCCESS; + break; + + default: + /* Unknown or unsupported OID */ + QueryResponse->InfoBufLength = 0U; + QueryResponse->Status = CDC_RNDIS_STATUS_FAILURE; + break; + } + + /* Setup the response buffer content */ + QueryResponse->MsgType = CDC_RNDIS_QUERY_CMPLT_ID; + QueryResponse->MsgLength = QueryResponse->InfoBufLength + 24U; + QueryResponse->ReqId = ReqId; + QueryResponse->InfoBufOffset = 16U; + + /* Set Response Ready field in order to send response during next control request */ + hcdc->ResponseRdy = 1U; + + /* Send Notification on Interrupt EP to inform Host that response is ready */ + (void)USBD_CDC_RNDIS_SendNotification(pdev, RNDIS_RESPONSE_AVAILABLE, 0U, NULL); + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_RNDIS_ProcessSetMsg + * Parse, extract data and check correctness of CDC_RNDIS Set Message command. + * @param pdev: USB Device Handle pointer + * @param Msg: Pointer to the message data extracted from SendEncapsulated command + * @retval status + */ +static uint8_t USBD_CDC_RNDIS_ProcessSetMsg(USBD_HandleTypeDef *pdev, + USBD_CDC_RNDIS_SetMsgTypeDef *Msg) +{ + /* Get the CDC_RNDIS handle pointer */ + USBD_CDC_RNDIS_HandleTypeDef *hcdc = (USBD_CDC_RNDIS_HandleTypeDef *)pdev->pClassData_CDC_RNDIS; + + /* Get and format the Msg input */ + USBD_CDC_RNDIS_SetMsgTypeDef *SetMessage = (USBD_CDC_RNDIS_SetMsgTypeDef *)Msg; + + /* Use same Msg input buffer as response buffer */ + USBD_CDC_RNDIS_SetCpltMsgTypeDef *SetResponse = (USBD_CDC_RNDIS_SetCpltMsgTypeDef *)(void *)Msg; + + /* Store the Message Request ID */ + uint32_t ReqId = SetMessage->ReqId; + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + switch (SetMessage->Oid) + { + case OID_GEN_CURRENT_PACKET_FILTER: + /* Setup the packet filter value */ + hcdc->PacketFilter = SetMessage->InfoBuf[0]; + SetResponse->Status = CDC_RNDIS_STATUS_SUCCESS; + break; + + case OID_802_3_MULTICAST_LIST: + /* List of multicast addresses on a miniport adapter */ + SetResponse->Status = CDC_RNDIS_STATUS_SUCCESS; + break; + + default: + /* Report an error */ + SetResponse->Status = CDC_RNDIS_STATUS_FAILURE; + break; + } + + /* Prepare response buffer */ + SetResponse->MsgType = CDC_RNDIS_SET_CMPLT_ID; + SetResponse->MsgLength = sizeof(USBD_CDC_RNDIS_SetCpltMsgTypeDef); + SetResponse->ReqId = ReqId; + + /* Set Response Ready field in order to send response during next control request */ + hcdc->ResponseRdy = 1U; + + /* Send Notification on Interrupt EP to inform Host that response is ready */ + (void)USBD_CDC_RNDIS_SendNotification(pdev, RNDIS_RESPONSE_AVAILABLE, 0U, NULL); + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_RNDIS_ProcessResetMsg + * Parse, extract data and check correctness of CDC_RNDIS Set Message command. + * @param pdev: USB Device Handle pointer + * @param Msg: Pointer to the message data extracted from SendEncapsulated command + * @retval status + */ +static uint8_t USBD_CDC_RNDIS_ProcessResetMsg(USBD_HandleTypeDef *pdev, + USBD_CDC_RNDIS_ResetMsgTypeDef *Msg) +{ + /* Get and format the Msg input */ + USBD_CDC_RNDIS_ResetMsgTypeDef *ResetMessage = (USBD_CDC_RNDIS_ResetMsgTypeDef *)Msg; + /* Get the CDC_RNDIS handle pointer */ + USBD_CDC_RNDIS_HandleTypeDef *hcdc = (USBD_CDC_RNDIS_HandleTypeDef *)pdev->pClassData_CDC_RNDIS; + /* Use same Msg input buffer as response buffer */ + USBD_CDC_RNDIS_ResetCpltMsgTypeDef *ResetResponse = (USBD_CDC_RNDIS_ResetCpltMsgTypeDef *)(void *)Msg; + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + if ((ResetMessage->MsgLength != sizeof(USBD_CDC_RNDIS_ResetMsgTypeDef)) || + (ResetMessage->Reserved != 0U)) + { + ResetResponse->Status = CDC_RNDIS_STATUS_FAILURE; + } + else + { + ResetResponse->Status = CDC_RNDIS_STATUS_SUCCESS; + } + + /* Prepare response buffer */ + ResetResponse->MsgType = CDC_RNDIS_RESET_CMPLT_ID; + ResetResponse->MsgLength = sizeof(USBD_CDC_RNDIS_ResetCpltMsgTypeDef); + ResetResponse->AddrReset = 0U; + + /* Set CDC_RNDIS state to INITIALIZED */ + hcdc->State = CDC_RNDIS_STATE_BUS_INITIALIZED; + hcdc->LinkStatus = 0U; + + /* Set Response Ready field in order to send response during next control request */ + hcdc->ResponseRdy = 1U; + + /* Send Notification on Interrupt EP to inform Host that response is ready */ + (void)USBD_CDC_RNDIS_SendNotification(pdev, RNDIS_RESPONSE_AVAILABLE, 0U, NULL); + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_RNDIS_ProcessPacketMsg + * Parse, extract data and check correctness of CDC_RNDIS Data Packet. + * @param pdev: USB Device Handle pointer + * @param Msg: Pointer to the message data extracted from Packet + * @retval status + */ +static uint8_t USBD_CDC_RNDIS_ProcessPacketMsg(USBD_HandleTypeDef *pdev, + USBD_CDC_RNDIS_PacketMsgTypeDef *Msg) +{ + uint32_t tmp1, tmp2; + + /* Get the CDC_RNDIS handle pointer */ + USBD_CDC_RNDIS_HandleTypeDef *hcdc = (USBD_CDC_RNDIS_HandleTypeDef *)pdev->pClassData_CDC_RNDIS; + + /* Get and format the Msg input */ + USBD_CDC_RNDIS_PacketMsgTypeDef *PacketMsg = (USBD_CDC_RNDIS_PacketMsgTypeDef *)Msg; + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + /* Check correctness of the message */ + if ((PacketMsg->MsgType != CDC_RNDIS_PACKET_MSG_ID)) + { + return (uint8_t)USBD_FAIL; + } + + /* Point to the payload and update the message length */ + + /* Use temporary storage variables to comply with MISRA-C 2012 rule of (+) operand allowed types */ + tmp1 = (uint32_t)PacketMsg; + tmp2 = (uint32_t)(PacketMsg->DataOffset); + hcdc->RxBuffer = (uint8_t *)(tmp1 + tmp2 + CDC_RNDIS_PCKTMSG_DATAOFFSET_OFFSET); + hcdc->RxLength = PacketMsg->DataLength; + + /* Process data by application */ + ((USBD_CDC_RNDIS_ItfTypeDef *)pdev->pUserData_CDC_RNDIS)->Receive(hcdc->RxBuffer, &hcdc->RxLength); + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CDC_RNDIS_ProcessUnsupportedMsg + * Parse, extract data and check correctness of CDC_RNDIS KeepAlive command. + * @param pdev: USB Device Handle pointer + * @param Msg: Pointer to the message data extracted from SendEncapsulated command + * @retval status + */ +static uint8_t USBD_CDC_RNDIS_ProcessUnsupportedMsg(USBD_HandleTypeDef *pdev, + USBD_CDC_RNDIS_CtrlMsgTypeDef *Msg) +{ + /* Get the CDC_RNDIS handle pointer */ + USBD_CDC_RNDIS_HandleTypeDef *hcdc = (USBD_CDC_RNDIS_HandleTypeDef *)pdev->pClassData_CDC_RNDIS; + + /* Use same Msg input buffer as response buffer */ + USBD_CDC_RNDIS_StsChangeMsgTypeDef *Response = (USBD_CDC_RNDIS_StsChangeMsgTypeDef *)(void *)Msg; + + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + + /* Setup the response buffer content */ + Response->MsgType = CDC_RNDIS_INDICATE_STATUS_MSG_ID; + Response->MsgLength = sizeof(USBD_CDC_RNDIS_StsChangeMsgTypeDef); + Response->Status = CDC_RNDIS_STATUS_NOT_SUPPORTED; + Response->StsBufLength = 0U; + Response->StsBufOffset = 20U; + + /* Set Response Ready field in order to send response during next control request */ + hcdc->ResponseRdy = 1U; + + /* Send Notification on Interrupt EP to inform Host that response is ready */ + (void)USBD_CDC_RNDIS_SendNotification(pdev, RNDIS_RESPONSE_AVAILABLE, 0U, NULL); + + UNUSED(Msg); + + return (uint8_t)USBD_OK; +} + +void USBD_Update_CDC_RNDIS_DESC(uint8_t *desc, + uint8_t cmd_itf, + uint8_t com_itf, + uint8_t in_ep, + uint8_t cmd_ep, + uint8_t out_ep, + uint8_t str_idx) +{ + desc[11] = cmd_itf; + desc[16] = str_idx; + desc[19] = cmd_itf; + desc[35] = com_itf; + desc[43] = cmd_itf; + desc[44] = com_itf; + desc[47] = cmd_ep; + desc[54] = com_itf; + desc[63] = out_ep; + desc[70] = in_ep; + + CDC_RNDIS_IN_EP = in_ep; + CDC_RNDIS_OUT_EP = out_ep; + CDC_RNDIS_CMD_EP = cmd_ep; + CDC_RNDIS_CMD_ITF_NBR = cmd_itf; + CDC_RNDIS_COM_ITF_NBR = com_itf; + CDC_RNDIS_STR_DESC_IDX = str_idx; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/DFU/Inc/usbd_dfu.h b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/DFU/Inc/usbd_dfu.h new file mode 100644 index 0000000..fb57b62 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/DFU/Inc/usbd_dfu.h @@ -0,0 +1,240 @@ +/** + ****************************************************************************** + * @file usbd_dfu.h + * @author MCD Application Team + * @brief Header file for the usbd_dfu.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_DFU_H +#define __USB_DFU_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ioreq.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_DFU + * @brief This file is the Header file for usbd_dfu.c + * @{ + */ + + +/** @defgroup USBD_DFU_Exported_Defines + * @{ + */ + +#define DFU_STR_DESC "STM32 USB DFU" + +#ifndef USBD_DFU_MAX_ITF_NUM +#define USBD_DFU_MAX_ITF_NUM 1U +#endif /* USBD_DFU_MAX_ITF_NUM */ + +#ifndef USBD_DFU_XFER_SIZE +#define USBD_DFU_XFER_SIZE 1024U +#endif /* USBD_DFU_XFER_SIZE */ + +#ifndef USBD_DFU_APP_DEFAULT_ADD +#define USBD_DFU_APP_DEFAULT_ADD 0x08008000U /* The first sector (32 KB) is reserved for DFU code */ +#endif /* USBD_DFU_APP_DEFAULT_ADD */ + +#define USB_DFU_CONFIG_DESC_SIZ (18U + (9U * USBD_DFU_MAX_ITF_NUM)) +#define USB_DFU_DESC_SIZ 9U + +#define DFU_DESCRIPTOR_TYPE 0x21U + + +/**************************************************/ +/* DFU Requests DFU states */ +/**************************************************/ +#define APP_STATE_IDLE 0U +#define APP_STATE_DETACH 1U +#define DFU_STATE_IDLE 2U +#define DFU_STATE_DNLOAD_SYNC 3U +#define DFU_STATE_DNLOAD_BUSY 4U +#define DFU_STATE_DNLOAD_IDLE 5U +#define DFU_STATE_MANIFEST_SYNC 6U +#define DFU_STATE_MANIFEST 7U +#define DFU_STATE_MANIFEST_WAIT_RESET 8U +#define DFU_STATE_UPLOAD_IDLE 9U +#define DFU_STATE_ERROR 10U + +/**************************************************/ +/* DFU errors */ +/**************************************************/ +#define DFU_ERROR_NONE 0x00U +#define DFU_ERROR_TARGET 0x01U +#define DFU_ERROR_FILE 0x02U +#define DFU_ERROR_WRITE 0x03U +#define DFU_ERROR_ERASE 0x04U +#define DFU_ERROR_CHECK_ERASED 0x05U +#define DFU_ERROR_PROG 0x06U +#define DFU_ERROR_VERIFY 0x07U +#define DFU_ERROR_ADDRESS 0x08U +#define DFU_ERROR_NOTDONE 0x09U +#define DFU_ERROR_FIRMWARE 0x0AU +#define DFU_ERROR_VENDOR 0x0BU +#define DFU_ERROR_USB 0x0CU +#define DFU_ERROR_POR 0x0DU +#define DFU_ERROR_UNKNOWN 0x0EU +#define DFU_ERROR_STALLEDPKT 0x0FU + +/**************************************************/ +/* DFU Manifestation State */ +/**************************************************/ +#define DFU_MANIFEST_COMPLETE 0x00U +#define DFU_MANIFEST_IN_PROGRESS 0x01U + + +/**************************************************/ +/* Special Commands with Download Request */ +/**************************************************/ +#define DFU_CMD_GETCOMMANDS 0x00U +#define DFU_CMD_SETADDRESSPOINTER 0x21U +#define DFU_CMD_ERASE 0x41U + +#define DFU_MEDIA_ERASE 0x00U +#define DFU_MEDIA_PROGRAM 0x01U + +/**************************************************/ +/* Other defines */ +/**************************************************/ +/* Bit Detach capable = bit 3 in bmAttributes field */ +#define DFU_DETACH_MASK (1U << 4) +#define DFU_STATUS_DEPTH 6U + +typedef enum +{ + DFU_DETACH = 0U, + DFU_DNLOAD, + DFU_UPLOAD, + DFU_GETSTATUS, + DFU_CLRSTATUS, + DFU_GETSTATE, + DFU_ABORT +} DFU_RequestTypeDef; + +typedef void (*pFunction)(void); + + +/********** Descriptor of DFU interface 0 Alternate setting n ****************/ +#define USBD_DFU_IF_DESC(n) 0x09, /* bLength: Interface Descriptor size */ \ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType */ \ + _DFU_ITF_NBR, /* bInterfaceNumber: Number of Interface */ \ + (n), /* bAlternateSetting: Alternate setting */ \ + 0x00, /* bNumEndpoints*/ \ + 0xFE, /* bInterfaceClass: Application Specific Class Code */ \ + 0x01, /* bInterfaceSubClass : Device Firmware Upgrade Code */ \ + 0x02, /* nInterfaceProtocol: DFU mode protocol */ \ + 0x00 /* iInterface: Index of string descriptor */ \ + +#define TRANSFER_SIZE_BYTES(size) ((uint8_t)(size)), /* XFERSIZEB0 */\ + ((uint8_t)((size) >> 8)) /* XFERSIZEB1 */ + +#define IS_PROTECTED_AREA(add) (uint8_t)((((add) >= 0x08000000) && ((add) < (APP_DEFAULT_ADD)))? 1:0) + +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_TypesDefinitions + * @{ + */ + +typedef struct +{ + union + { + uint32_t d32[USBD_DFU_XFER_SIZE / 4U]; + uint8_t d8[USBD_DFU_XFER_SIZE]; + } buffer; + + uint32_t wblock_num; + uint32_t wlength; + uint32_t data_ptr; + uint32_t alt_setting; + + uint8_t dev_status[DFU_STATUS_DEPTH]; + uint8_t ReservedForAlign[2]; + uint8_t dev_state; + uint8_t manif_state; +} USBD_DFU_HandleTypeDef; + +typedef struct +{ + const uint8_t *pStrDesc; + uint16_t (*Init)(void); + uint16_t (*DeInit)(void); + uint16_t (*Erase)(uint32_t Add); + uint16_t (*Write)(uint8_t *src, uint8_t *dest, uint32_t Len); + uint8_t *(*Read)(uint8_t *src, uint8_t *dest, uint32_t Len); + uint16_t (*GetStatus)(uint32_t Add, uint8_t cmd, uint8_t *buff); +} USBD_DFU_MediaTypeDef; +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_Variables + * @{ + */ + +extern USBD_ClassTypeDef USBD_DFU; + +extern uint8_t DFU_ITF_NBR; +extern uint8_t DFU_STR_DESC_IDX; + +/** + * @} + */ + +/** @defgroup USB_CORE_Exported_Functions + * @{ + */ +uint8_t USBD_DFU_RegisterMedia(USBD_HandleTypeDef *pdev, + USBD_DFU_MediaTypeDef *fops); + +void USBD_Update_DFU_DESC(uint8_t *desc, uint8_t itf_no, uint8_t str_idx); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_DFU_H */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/DFU/Src/usbd_dfu.c b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/DFU/Src/usbd_dfu.c new file mode 100644 index 0000000..8538734 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/DFU/Src/usbd_dfu.c @@ -0,0 +1,1143 @@ +/** + ****************************************************************************** + * @file usbd_dfu.c + * @author MCD Application Team + * @brief This file provides the DFU core functions. + * + * @verbatim + * + * =================================================================== + * DFU Class Driver Description + * =================================================================== + * This driver manages the DFU class V1.1 following the "Device Class Specification for + * Device Firmware Upgrade Version 1.1 Aug 5, 2004". + * This driver implements the following aspects of the specification: + * - Device descriptor management + * - Configuration descriptor management + * - Enumeration as DFU device (in DFU mode only) + * - Requests management (supporting ST DFU sub-protocol) + * - Memory operations management (Download/Upload/Erase/Detach/GetState/GetStatus) + * - DFU state machine implementation. + * + * @note + * ST DFU sub-protocol is compliant with DFU protocol and use sub-requests to manage + * memory addressing, commands processing, specific memories operations (ie. Erase) ... + * As required by the DFU specification, only endpoint 0 is used in this application. + * Other endpoints and functions may be added to the application (ie. DFU ...) + * + * These aspects may be enriched or modified for a specific user application. + * + * This driver doesn't implement the following aspects of the specification + * (but it is possible to manage these features with some modifications on this driver): + * - Manifestation Tolerant mode + * + * @endverbatim + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* BSPDependencies +- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" +- "stm32xxxxx_{eval}{discovery}_io.c" +EndBSPDependencies */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_dfu.h" +#include "usbd_ctlreq.h" + +#define _DFU_ITF_NBR 0x00 +#define _DFU_STR_DESC_IDX 0x01 + +uint8_t DFU_ITF_NBR = _DFU_ITF_NBR; +uint8_t DFU_STR_DESC_IDX = _DFU_STR_DESC_IDX; + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_DFU + * @brief usbd core module + * @{ + */ + +/** @defgroup USBD_DFU_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_DFU_Private_Defines + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_DFU_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_DFU_Private_FunctionPrototypes + * @{ + */ + +static uint8_t USBD_DFU_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_DFU_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_DFU_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static uint8_t USBD_DFU_EP0_RxReady(USBD_HandleTypeDef *pdev); +static uint8_t USBD_DFU_EP0_TxReady(USBD_HandleTypeDef *pdev); +static uint8_t USBD_DFU_SOF(USBD_HandleTypeDef *pdev); + +static uint8_t *USBD_DFU_GetCfgDesc(uint16_t *length); +static uint8_t *USBD_DFU_GetDeviceQualifierDesc(uint16_t *length); + +#if (USBD_SUPPORT_USER_STRING_DESC == 1U) +static uint8_t *USBD_DFU_GetUsrStringDesc(USBD_HandleTypeDef *pdev, + uint8_t index, uint16_t *length); +#endif + +static void DFU_Detach(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static void DFU_Download(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static void DFU_Upload(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static void DFU_GetStatus(USBD_HandleTypeDef *pdev); +static void DFU_ClearStatus(USBD_HandleTypeDef *pdev); +static void DFU_GetState(USBD_HandleTypeDef *pdev); +static void DFU_Abort(USBD_HandleTypeDef *pdev); +static void DFU_Leave(USBD_HandleTypeDef *pdev); + +/** + * @} + */ + +/** @defgroup USBD_DFU_Private_Variables + * @{ + */ + +static USBD_DFU_HandleTypeDef DFU_Instance; + +USBD_ClassTypeDef USBD_DFU = + { + USBD_DFU_Init, + USBD_DFU_DeInit, + USBD_DFU_Setup, + USBD_DFU_EP0_TxReady, + USBD_DFU_EP0_RxReady, + NULL, + NULL, + USBD_DFU_SOF, + NULL, + NULL, + USBD_DFU_GetCfgDesc, + USBD_DFU_GetCfgDesc, + USBD_DFU_GetCfgDesc, + USBD_DFU_GetDeviceQualifierDesc, +#if (USBD_SUPPORT_USER_STRING_DESC == 1U) + USBD_DFU_GetUsrStringDesc +#endif +}; + +/* USB DFU device Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_DFU_CfgDesc[USB_DFU_CONFIG_DESC_SIZ] __ALIGN_END = + { + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_DFU_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */ + 0x00, + 0x01, /* bNumInterfaces: 1 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x02, /* iConfiguration: Index of string descriptor describing the configuration */ +#if (USBD_SELF_POWERED == 1U) + 0xC0, /* bmAttributes: Bus Powered according to user configuration */ +#else + 0x80, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* MaxPower (mA) */ + /* 09 */ + + /********** Descriptor of DFU interface 0 Alternate setting 0 **************/ + USBD_DFU_IF_DESC(0U), /* This interface is mandatory for all devices */ + +#if (USBD_DFU_MAX_ITF_NUM > 1U) + /********** Descriptor of DFU interface 0 Alternate setting 1 **************/ + USBD_DFU_IF_DESC(1), +#endif /* (USBD_DFU_MAX_ITF_NUM > 1) */ + +#if (USBD_DFU_MAX_ITF_NUM > 2U) + /********** Descriptor of DFU interface 0 Alternate setting 2 **************/ + USBD_DFU_IF_DESC(2), +#endif /* (USBD_DFU_MAX_ITF_NUM > 2) */ + +#if (USBD_DFU_MAX_ITF_NUM > 3U) + /********** Descriptor of DFU interface 0 Alternate setting 3 **************/ + USBD_DFU_IF_DESC(3), +#endif /* (USBD_DFU_MAX_ITF_NUM > 3) */ + +#if (USBD_DFU_MAX_ITF_NUM > 4U) + /********** Descriptor of DFU interface 0 Alternate setting 4 **************/ + USBD_DFU_IF_DESC(4), +#endif /* (USBD_DFU_MAX_ITF_NUM > 4) */ + +#if (USBD_DFU_MAX_ITF_NUM > 5U) + /********** Descriptor of DFU interface 0 Alternate setting 5 **************/ + USBD_DFU_IF_DESC(5), +#endif /* (USBD_DFU_MAX_ITF_NUM > 5) */ + +#if (USBD_DFU_MAX_ITF_NUM > 6U) +#error "ERROR: usbd_dfu_core.c: Modify the file to support more descriptors!" +#endif /* (USBD_DFU_MAX_ITF_NUM > 6) */ + + /******************** DFU Functional Descriptor********************/ + 0x09, /* blength = 9 Bytes */ + DFU_DESCRIPTOR_TYPE, /* DFU Functional Descriptor */ + 0x0B, /* bmAttribute: bitCanDnload = 1 (bit 0) + bitCanUpload = 1 (bit 1) + bitManifestationTolerant = 0 (bit 2) + bitWillDetach = 1 (bit 3) + Reserved (bit4-6) + bitAcceleratedST = 0 (bit 7) */ + 0xFF, /* DetachTimeOut= 255 ms*/ + 0x00, + /* WARNING: In DMA mode the multiple MPS packets feature is still not supported + ==> In this case, when using DMA USBD_DFU_XFER_SIZE should be set to 64 in usbd_conf.h */ + TRANSFER_SIZE_BYTES(USBD_DFU_XFER_SIZE), /* TransferSize = 1024 Byte */ + 0x1A, /* bcdDFUVersion */ + 0x01 + /***********************************************************/ + /* 9*/ +}; + +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_DFU_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_DFU_Private_Functions + * @{ + */ + +/** + * @brief USBD_DFU_Init + * Initialize the DFU interface + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_DFU_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(cfgidx); + + USBD_DFU_HandleTypeDef *hdfu; + + /* Allocate Audio structure */ + hdfu = &DFU_Instance; + + if (hdfu == NULL) + { + pdev->pClassData_DFU = NULL; + return (uint8_t)USBD_EMEM; + } + + pdev->pClassData_DFU = (void *)hdfu; + + hdfu->alt_setting = 0U; + hdfu->data_ptr = USBD_DFU_APP_DEFAULT_ADD; + hdfu->wblock_num = 0U; + hdfu->wlength = 0U; + + hdfu->manif_state = DFU_MANIFEST_COMPLETE; + hdfu->dev_state = DFU_STATE_IDLE; + + hdfu->dev_status[0] = DFU_ERROR_NONE; + hdfu->dev_status[1] = 0U; + hdfu->dev_status[2] = 0U; + hdfu->dev_status[3] = 0U; + hdfu->dev_status[4] = DFU_STATE_IDLE; + hdfu->dev_status[5] = 0U; + + /* Initialize Hardware layer */ + if (((USBD_DFU_MediaTypeDef *)pdev->pUserData_DFU)->Init() != USBD_OK) + { + return (uint8_t)USBD_FAIL; + } + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_DFU_Init + * De-Initialize the DFU layer + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_DFU_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(cfgidx); + USBD_DFU_HandleTypeDef *hdfu; + + if (pdev->pClassData_DFU == NULL) + { + return (uint8_t)USBD_EMEM; + } + + hdfu = (USBD_DFU_HandleTypeDef *)pdev->pClassData_DFU; + hdfu->wblock_num = 0U; + hdfu->wlength = 0U; + + hdfu->dev_state = DFU_STATE_IDLE; + hdfu->dev_status[0] = DFU_ERROR_NONE; + hdfu->dev_status[4] = DFU_STATE_IDLE; + + /* DeInit physical Interface components and Hardware Layer */ + ((USBD_DFU_MediaTypeDef *)pdev->pUserData_DFU)->DeInit(); +#if (0) + USBD_free(pdev->pClassData_DFU); +#endif + pdev->pClassData_DFU = NULL; + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_DFU_Setup + * Handle the DFU specific requests + * @param pdev: instance + * @param req: usb requests + * @retval status + */ +static uint8_t USBD_DFU_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_DFU_HandleTypeDef *hdfu = (USBD_DFU_HandleTypeDef *)pdev->pClassData_DFU; + USBD_StatusTypeDef ret = USBD_OK; + uint8_t *pbuf = NULL; + uint16_t len = 0U; + uint16_t status_info = 0U; + + if (hdfu == NULL) + { + return (uint8_t)USBD_FAIL; + } + + switch (req->bmRequest & USB_REQ_TYPE_MASK) + { + case USB_REQ_TYPE_CLASS: + switch (req->bRequest) + { + case DFU_DNLOAD: + DFU_Download(pdev, req); + break; + + case DFU_UPLOAD: + DFU_Upload(pdev, req); + break; + + case DFU_GETSTATUS: + DFU_GetStatus(pdev); + break; + + case DFU_CLRSTATUS: + DFU_ClearStatus(pdev); + break; + + case DFU_GETSTATE: + DFU_GetState(pdev); + break; + + case DFU_ABORT: + DFU_Abort(pdev); + break; + + case DFU_DETACH: + DFU_Detach(pdev, req); + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + break; + + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) + { + case USB_REQ_GET_STATUS: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_GET_DESCRIPTOR: + if ((req->wValue >> 8) == DFU_DESCRIPTOR_TYPE) + { + pbuf = USBD_DFU_CfgDesc + (9U * (USBD_DFU_MAX_ITF_NUM + 1U)); + len = MIN(USB_DFU_DESC_SIZ, req->wLength); + } + + (void)USBD_CtlSendData(pdev, pbuf, len); + break; + + case USB_REQ_GET_INTERFACE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, (uint8_t *)&hdfu->alt_setting, 1U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_SET_INTERFACE: + if ((uint8_t)(req->wValue) < USBD_DFU_MAX_ITF_NUM) + { + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + hdfu->alt_setting = (uint8_t)(req->wValue); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + } + else + { + /* Call the error management function (command will be NAKed */ + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_CLEAR_FEATURE: + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + + return (uint8_t)ret; +} + +/** + * @brief USBD_DFU_GetCfgDesc + * return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_DFU_GetCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_DFU_CfgDesc); + + return USBD_DFU_CfgDesc; +} + +/** + * @brief USBD_DFU_EP0_RxReady + * handle EP0 Rx Ready event + * @param pdev: device instance + * @retval status + */ +static uint8_t USBD_DFU_EP0_RxReady(USBD_HandleTypeDef *pdev) +{ + UNUSED(pdev); + + return (uint8_t)USBD_OK; +} +/** + * @brief USBD_DFU_EP0_TxReady + * handle EP0 TRx Ready event + * @param pdev: device instance + * @retval status + */ +static uint8_t USBD_DFU_EP0_TxReady(USBD_HandleTypeDef *pdev) +{ + USBD_SetupReqTypedef req; + uint32_t addr; + USBD_DFU_HandleTypeDef *hdfu = (USBD_DFU_HandleTypeDef *)pdev->pClassData_DFU; + USBD_DFU_MediaTypeDef *DfuInterface = (USBD_DFU_MediaTypeDef *)pdev->pUserData_DFU; + + if (hdfu == NULL) + { + return (uint8_t)USBD_FAIL; + } + + if (hdfu->dev_state == DFU_STATE_DNLOAD_BUSY) + { + /* Decode the Special Command */ + if (hdfu->wblock_num == 0U) + { + if (hdfu->wlength == 1U) + { + if (hdfu->buffer.d8[0] == DFU_CMD_GETCOMMANDS) + { + /* Nothing to do */ + } + } + else if (hdfu->wlength == 5U) + { + if (hdfu->buffer.d8[0] == DFU_CMD_SETADDRESSPOINTER) + { + hdfu->data_ptr = hdfu->buffer.d8[1]; + hdfu->data_ptr += (uint32_t)hdfu->buffer.d8[2] << 8; + hdfu->data_ptr += (uint32_t)hdfu->buffer.d8[3] << 16; + hdfu->data_ptr += (uint32_t)hdfu->buffer.d8[4] << 24; + } + else if (hdfu->buffer.d8[0] == DFU_CMD_ERASE) + { + hdfu->data_ptr = hdfu->buffer.d8[1]; + hdfu->data_ptr += (uint32_t)hdfu->buffer.d8[2] << 8; + hdfu->data_ptr += (uint32_t)hdfu->buffer.d8[3] << 16; + hdfu->data_ptr += (uint32_t)hdfu->buffer.d8[4] << 24; + + if (DfuInterface->Erase(hdfu->data_ptr) != USBD_OK) + { + return (uint8_t)USBD_FAIL; + } + } + else + { + return (uint8_t)USBD_FAIL; + } + } + else + { + /* Reset the global length and block number */ + hdfu->wlength = 0U; + hdfu->wblock_num = 0U; + /* Call the error management function (command will be NAKed) */ + req.bmRequest = 0U; + req.wLength = 1U; + USBD_CtlError(pdev, &req); + } + } + /* Regular Download Command */ + else + { + if (hdfu->wblock_num > 1U) + { + /* Decode the required address */ + addr = ((hdfu->wblock_num - 2U) * USBD_DFU_XFER_SIZE) + hdfu->data_ptr; + + /* Perform the write operation */ + if (DfuInterface->Write(hdfu->buffer.d8, (uint8_t *)addr, hdfu->wlength) != USBD_OK) + { + return (uint8_t)USBD_FAIL; + } + } + } + + /* Reset the global length and block number */ + hdfu->wlength = 0U; + hdfu->wblock_num = 0U; + + /* Update the state machine */ + hdfu->dev_state = DFU_STATE_DNLOAD_SYNC; + + hdfu->dev_status[1] = 0U; + hdfu->dev_status[2] = 0U; + hdfu->dev_status[3] = 0U; + hdfu->dev_status[4] = hdfu->dev_state; + } + else if (hdfu->dev_state == DFU_STATE_MANIFEST) /* Manifestation in progress */ + { + /* Start leaving DFU mode */ + DFU_Leave(pdev); + } + else + { + return (uint8_t)USBD_FAIL; + } + + return (uint8_t)USBD_OK; +} +/** + * @brief USBD_DFU_SOF + * handle SOF event + * @param pdev: device instance + * @retval status + */ +static uint8_t USBD_DFU_SOF(USBD_HandleTypeDef *pdev) +{ + UNUSED(pdev); + + return (uint8_t)USBD_OK; +} + +/** + * @brief DeviceQualifierDescriptor + * return Device Qualifier descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_DFU_GetDeviceQualifierDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_DFU_DeviceQualifierDesc); + + return USBD_DFU_DeviceQualifierDesc; +} + +/** + * @brief USBD_DFU_GetUsrStringDesc + * Manages the transfer of memory interfaces string descriptors. + * @param speed : current device speed + * @param index: descriptor index + * @param length : pointer data length + * @retval pointer to the descriptor table or NULL if the descriptor is not supported. + */ +#if (USBD_SUPPORT_USER_STRING_DESC == 1U) +static uint8_t *USBD_DFU_GetUsrStringDesc(USBD_HandleTypeDef *pdev, uint8_t index, uint16_t *length) +{ + static uint8_t USBD_StrDesc[255]; + USBD_DFU_MediaTypeDef *DfuInterface = (USBD_DFU_MediaTypeDef *)pdev->pUserData_DFU; + + /* Check if the requested string interface is supported */ + if (index <= (USBD_IDX_INTERFACE_STR + USBD_DFU_MAX_ITF_NUM)) + { + USBD_GetString((uint8_t *)DfuInterface->pStrDesc, USBD_StrDesc, length); + return USBD_StrDesc; + } + else + { + /* Not supported Interface Descriptor index */ + return NULL; + } +} +#endif + +/** + * @brief USBD_MSC_RegisterStorage + * @param fops: storage callback + * @retval status + */ +uint8_t USBD_DFU_RegisterMedia(USBD_HandleTypeDef *pdev, + USBD_DFU_MediaTypeDef *fops) +{ + if (fops == NULL) + { + return (uint8_t)USBD_FAIL; + } + + pdev->pUserData_DFU = fops; + + return (uint8_t)USBD_OK; +} + +/****************************************************************************** + DFU Class requests management + ******************************************************************************/ +/** + * @brief DFU_Detach + * Handles the DFU DETACH request. + * @param pdev: device instance + * @param req: pointer to the request structure. + * @retval None. + */ +static void DFU_Detach(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_DFU_HandleTypeDef *hdfu = (USBD_DFU_HandleTypeDef *)pdev->pClassData_DFU; + + if (hdfu == NULL) + { + return; + } + + if ((hdfu->dev_state == DFU_STATE_IDLE) || + (hdfu->dev_state == DFU_STATE_DNLOAD_SYNC) || + (hdfu->dev_state == DFU_STATE_DNLOAD_IDLE) || + (hdfu->dev_state == DFU_STATE_MANIFEST_SYNC) || + (hdfu->dev_state == DFU_STATE_UPLOAD_IDLE)) + { + /* Update the state machine */ + hdfu->dev_state = DFU_STATE_IDLE; + hdfu->dev_status[0] = DFU_ERROR_NONE; + hdfu->dev_status[1] = 0U; + hdfu->dev_status[2] = 0U; + hdfu->dev_status[3] = 0U; /*bwPollTimeout=0ms*/ + hdfu->dev_status[4] = hdfu->dev_state; + hdfu->dev_status[5] = 0U; /*iString*/ + hdfu->wblock_num = 0U; + hdfu->wlength = 0U; + } + + /* Check the detach capability in the DFU functional descriptor */ + if (((USBD_DFU_CfgDesc[12U + (9U * USBD_DFU_MAX_ITF_NUM)]) & DFU_DETACH_MASK) != 0U) + { + /* Perform an Attach-Detach operation on USB bus */ + (void)USBD_Stop(pdev); + (void)USBD_Start(pdev); + } + else + { + /* Wait for the period of time specified in Detach request */ + USBD_Delay((uint32_t)req->wValue); + } +} + +/** + * @brief DFU_Download + * Handles the DFU DNLOAD request. + * @param pdev: device instance + * @param req: pointer to the request structure + * @retval None + */ +static void DFU_Download(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_DFU_HandleTypeDef *hdfu = (USBD_DFU_HandleTypeDef *)pdev->pClassData_DFU; + + if (hdfu == NULL) + { + return; + } + + /* Data setup request */ + if (req->wLength > 0U) + { + if ((hdfu->dev_state == DFU_STATE_IDLE) || (hdfu->dev_state == DFU_STATE_DNLOAD_IDLE)) + { + /* Update the global length and block number */ + hdfu->wblock_num = req->wValue; + hdfu->wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE); + + /* Update the state machine */ + hdfu->dev_state = DFU_STATE_DNLOAD_SYNC; + hdfu->dev_status[4] = hdfu->dev_state; + + /* Prepare the reception of the buffer over EP0 */ + (void)USBD_CtlPrepareRx(pdev, (uint8_t *)hdfu->buffer.d8, hdfu->wlength); + } + /* Unsupported state */ + else + { + /* Call the error management function (command will be NAKed */ + USBD_CtlError(pdev, req); + } + } + /* 0 Data DNLOAD request */ + else + { + /* End of DNLOAD operation*/ + if ((hdfu->dev_state == DFU_STATE_DNLOAD_IDLE) || (hdfu->dev_state == DFU_STATE_IDLE)) + { + hdfu->manif_state = DFU_MANIFEST_IN_PROGRESS; + hdfu->dev_state = DFU_STATE_MANIFEST_SYNC; + hdfu->dev_status[1] = 0U; + hdfu->dev_status[2] = 0U; + hdfu->dev_status[3] = 0U; + hdfu->dev_status[4] = hdfu->dev_state; + } + else + { + /* Call the error management function (command will be NAKed */ + USBD_CtlError(pdev, req); + } + } +} + +/** + * @brief DFU_Upload + * Handles the DFU UPLOAD request. + * @param pdev: instance + * @param req: pointer to the request structure + * @retval status + */ +static void DFU_Upload(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_DFU_HandleTypeDef *hdfu = (USBD_DFU_HandleTypeDef *)pdev->pClassData_DFU; + USBD_DFU_MediaTypeDef *DfuInterface = (USBD_DFU_MediaTypeDef *)pdev->pUserData_DFU; + uint8_t *phaddr; + uint32_t addr; + + if (hdfu == NULL) + { + return; + } + + /* Data setup request */ + if (req->wLength > 0U) + { + if ((hdfu->dev_state == DFU_STATE_IDLE) || (hdfu->dev_state == DFU_STATE_UPLOAD_IDLE)) + { + /* Update the global length and block number */ + hdfu->wblock_num = req->wValue; + hdfu->wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE); + + /* DFU Get Command */ + if (hdfu->wblock_num == 0U) + { + /* Update the state machine */ + hdfu->dev_state = (hdfu->wlength > 3U) ? DFU_STATE_IDLE : DFU_STATE_UPLOAD_IDLE; + + hdfu->dev_status[1] = 0U; + hdfu->dev_status[2] = 0U; + hdfu->dev_status[3] = 0U; + hdfu->dev_status[4] = hdfu->dev_state; + + /* Store the values of all supported commands */ + hdfu->buffer.d8[0] = DFU_CMD_GETCOMMANDS; + hdfu->buffer.d8[1] = DFU_CMD_SETADDRESSPOINTER; + hdfu->buffer.d8[2] = DFU_CMD_ERASE; + + /* Send the status data over EP0 */ + (void)USBD_CtlSendData(pdev, (uint8_t *)(&(hdfu->buffer.d8[0])), 3U); + } + else if (hdfu->wblock_num > 1U) + { + hdfu->dev_state = DFU_STATE_UPLOAD_IDLE; + + hdfu->dev_status[1] = 0U; + hdfu->dev_status[2] = 0U; + hdfu->dev_status[3] = 0U; + hdfu->dev_status[4] = hdfu->dev_state; + + addr = ((hdfu->wblock_num - 2U) * USBD_DFU_XFER_SIZE) + hdfu->data_ptr; + + /* Return the physical address where data are stored */ + phaddr = DfuInterface->Read((uint8_t *)addr, hdfu->buffer.d8, hdfu->wlength); + + /* Send the status data over EP0 */ + (void)USBD_CtlSendData(pdev, phaddr, hdfu->wlength); + } + else /* unsupported hdfu->wblock_num */ + { + hdfu->dev_state = DFU_ERROR_STALLEDPKT; + + hdfu->dev_status[1] = 0U; + hdfu->dev_status[2] = 0U; + hdfu->dev_status[3] = 0U; + hdfu->dev_status[4] = hdfu->dev_state; + + /* Call the error management function (command will be NAKed */ + USBD_CtlError(pdev, req); + } + } + /* Unsupported state */ + else + { + hdfu->wlength = 0U; + hdfu->wblock_num = 0U; + + /* Call the error management function (command will be NAKed */ + USBD_CtlError(pdev, req); + } + } + /* No Data setup request */ + else + { + hdfu->dev_state = DFU_STATE_IDLE; + + hdfu->dev_status[1] = 0U; + hdfu->dev_status[2] = 0U; + hdfu->dev_status[3] = 0U; + hdfu->dev_status[4] = hdfu->dev_state; + } +} + +/** + * @brief DFU_GetStatus + * Handles the DFU GETSTATUS request. + * @param pdev: instance + * @retval status + */ +static void DFU_GetStatus(USBD_HandleTypeDef *pdev) +{ + USBD_DFU_HandleTypeDef *hdfu = (USBD_DFU_HandleTypeDef *)pdev->pClassData_DFU; + USBD_DFU_MediaTypeDef *DfuInterface = (USBD_DFU_MediaTypeDef *)pdev->pUserData_DFU; + + if (hdfu == NULL) + { + return; + } + + switch (hdfu->dev_state) + { + case DFU_STATE_DNLOAD_SYNC: + if (hdfu->wlength != 0U) + { + hdfu->dev_state = DFU_STATE_DNLOAD_BUSY; + + hdfu->dev_status[1] = 0U; + hdfu->dev_status[2] = 0U; + hdfu->dev_status[3] = 0U; + hdfu->dev_status[4] = hdfu->dev_state; + + if ((hdfu->wblock_num == 0U) && (hdfu->buffer.d8[0] == DFU_CMD_ERASE)) + { + DfuInterface->GetStatus(hdfu->data_ptr, DFU_MEDIA_ERASE, hdfu->dev_status); + } + else + { + DfuInterface->GetStatus(hdfu->data_ptr, DFU_MEDIA_PROGRAM, hdfu->dev_status); + } + } + else /* (hdfu->wlength==0)*/ + { + hdfu->dev_state = DFU_STATE_DNLOAD_IDLE; + + hdfu->dev_status[1] = 0U; + hdfu->dev_status[2] = 0U; + hdfu->dev_status[3] = 0U; + hdfu->dev_status[4] = hdfu->dev_state; + } + break; + + case DFU_STATE_MANIFEST_SYNC: + if (hdfu->manif_state == DFU_MANIFEST_IN_PROGRESS) + { + hdfu->dev_state = DFU_STATE_MANIFEST; + + hdfu->dev_status[1] = 1U; /*bwPollTimeout = 1ms*/ + hdfu->dev_status[2] = 0U; + hdfu->dev_status[3] = 0U; + hdfu->dev_status[4] = hdfu->dev_state; + } + else + { + if ((hdfu->manif_state == DFU_MANIFEST_COMPLETE) && + (((USBD_DFU_CfgDesc[(11U + (9U * USBD_DFU_MAX_ITF_NUM))]) & 0x04U) != 0U)) + { + hdfu->dev_state = DFU_STATE_IDLE; + + hdfu->dev_status[1] = 0U; + hdfu->dev_status[2] = 0U; + hdfu->dev_status[3] = 0U; + hdfu->dev_status[4] = hdfu->dev_state; + } + } + break; + + default: + break; + } + + /* Send the status data over EP0 */ + (void)USBD_CtlSendData(pdev, (uint8_t *)(&(hdfu->dev_status[0])), 6U); +} + +/** + * @brief DFU_ClearStatus + * Handles the DFU CLRSTATUS request. + * @param pdev: device instance + * @retval status + */ +static void DFU_ClearStatus(USBD_HandleTypeDef *pdev) +{ + USBD_DFU_HandleTypeDef *hdfu = (USBD_DFU_HandleTypeDef *)pdev->pClassData_DFU; + + if (hdfu == NULL) + { + return; + } + + if (hdfu->dev_state == DFU_STATE_ERROR) + { + hdfu->dev_state = DFU_STATE_IDLE; + hdfu->dev_status[0] = DFU_ERROR_NONE; /* bStatus */ + hdfu->dev_status[1] = 0U; + hdfu->dev_status[2] = 0U; + hdfu->dev_status[3] = 0U; /* bwPollTimeout=0ms */ + hdfu->dev_status[4] = hdfu->dev_state; /* bState */ + hdfu->dev_status[5] = 0U; /* iString */ + } + else + { + /* State Error */ + hdfu->dev_state = DFU_STATE_ERROR; + hdfu->dev_status[0] = DFU_ERROR_UNKNOWN; /* bStatus */ + hdfu->dev_status[1] = 0U; + hdfu->dev_status[2] = 0U; + hdfu->dev_status[3] = 0U; /* bwPollTimeout=0ms */ + hdfu->dev_status[4] = hdfu->dev_state; /* bState */ + hdfu->dev_status[5] = 0U; /* iString */ + } +} + +/** + * @brief DFU_GetState + * Handles the DFU GETSTATE request. + * @param pdev: device instance + * @retval None + */ +static void DFU_GetState(USBD_HandleTypeDef *pdev) +{ + USBD_DFU_HandleTypeDef *hdfu = (USBD_DFU_HandleTypeDef *)pdev->pClassData_DFU; + + if (hdfu == NULL) + { + return; + } + + /* Return the current state of the DFU interface */ + (void)USBD_CtlSendData(pdev, &hdfu->dev_state, 1U); +} + +/** + * @brief DFU_Abort + * Handles the DFU ABORT request. + * @param pdev: device instance + * @retval None + */ +static void DFU_Abort(USBD_HandleTypeDef *pdev) +{ + USBD_DFU_HandleTypeDef *hdfu = (USBD_DFU_HandleTypeDef *)pdev->pClassData_DFU; + + if (hdfu == NULL) + { + return; + } + + if ((hdfu->dev_state == DFU_STATE_IDLE) || + (hdfu->dev_state == DFU_STATE_DNLOAD_SYNC) || + (hdfu->dev_state == DFU_STATE_DNLOAD_IDLE) || + (hdfu->dev_state == DFU_STATE_MANIFEST_SYNC) || + (hdfu->dev_state == DFU_STATE_UPLOAD_IDLE)) + { + hdfu->dev_state = DFU_STATE_IDLE; + hdfu->dev_status[0] = DFU_ERROR_NONE; + hdfu->dev_status[1] = 0U; + hdfu->dev_status[2] = 0U; + hdfu->dev_status[3] = 0U; /* bwPollTimeout=0ms */ + hdfu->dev_status[4] = hdfu->dev_state; + hdfu->dev_status[5] = 0U; /* iString */ + hdfu->wblock_num = 0U; + hdfu->wlength = 0U; + } +} + +/** + * @brief DFU_Leave + * Handles the sub-protocol DFU leave DFU mode request (leaves DFU mode + * and resets device to jump to user loaded code). + * @param pdev: device instance + * @retval None + */ +static void DFU_Leave(USBD_HandleTypeDef *pdev) +{ + USBD_DFU_HandleTypeDef *hdfu = (USBD_DFU_HandleTypeDef *)pdev->pClassData_DFU; + + if (hdfu == NULL) + { + return; + } + + hdfu->manif_state = DFU_MANIFEST_COMPLETE; + + if (((USBD_DFU_CfgDesc[(11U + (9U * USBD_DFU_MAX_ITF_NUM))]) & 0x04U) != 0U) + { + hdfu->dev_state = DFU_STATE_MANIFEST_SYNC; + + hdfu->dev_status[1] = 0U; + hdfu->dev_status[2] = 0U; + hdfu->dev_status[3] = 0U; + hdfu->dev_status[4] = hdfu->dev_state; + return; + } + else + { + hdfu->dev_state = DFU_STATE_MANIFEST_WAIT_RESET; + + hdfu->dev_status[1] = 0U; + hdfu->dev_status[2] = 0U; + hdfu->dev_status[3] = 0U; + hdfu->dev_status[4] = hdfu->dev_state; + + /* Disconnect the USB device */ + (void)USBD_Stop(pdev); + + /* Generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); + + /* The next instructions will not be reached (system reset) */ + } +} + +void USBD_Update_DFU_DESC(uint8_t *desc, uint8_t itf_no, uint8_t str_idx) +{ + desc[11] = itf_no; + desc[17] = str_idx; + +#if (USBD_DFU_MAX_ITF_NUM > 1U) + desc[20] = itf_no; +#endif /* (USBD_DFU_MAX_ITF_NUM > 1) */ + +#if (USBD_DFU_MAX_ITF_NUM > 2U) + desc[29] = itf_no; +#endif /* (USBD_DFU_MAX_ITF_NUM > 2) */ + +#if (USBD_DFU_MAX_ITF_NUM > 3U) + desc[38] = itf_no; +#endif /* (USBD_DFU_MAX_ITF_NUM > 3) */ + +#if (USBD_DFU_MAX_ITF_NUM > 4U) + desc[47] = itf_no; +#endif /* (USBD_DFU_MAX_ITF_NUM > 4) */ + +#if (USBD_DFU_MAX_ITF_NUM > 5U) + desc[56] = itf_no; +#endif /* (USBD_DFU_MAX_ITF_NUM > 5) */ + + DFU_ITF_NBR = itf_no; + DFU_STR_DESC_IDX = str_idx; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/HID_CUSTOM/Inc/usbd_hid_custom.h b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/HID_CUSTOM/Inc/usbd_hid_custom.h new file mode 100644 index 0000000..1509003 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/HID_CUSTOM/Inc/usbd_hid_custom.h @@ -0,0 +1,168 @@ +/** + ****************************************************************************** + * @file usbd_customhid.h + * @author MCD Application Team + * @brief header file for the usbd_customhid.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_CUSTOMHID_H +#define __USB_CUSTOMHID_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ioreq.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_CUSTOM_HID + * @brief This file is the Header file for USBD_customhid.c + * @{ + */ + + +/** @defgroup USBD_CUSTOM_HID_Exported_Defines + * @{ + */ + +#define CUSTOM_HID_STR_DESC "STM32 HID CUSTOM" + +#define CUSTOM_HID_EPIN_SIZE 0x02U +#define CUSTOM_HID_EPOUT_SIZE 0x02U + +#define USB_CUSTOM_HID_CONFIG_DESC_SIZ 41U +#define USB_CUSTOM_HID_DESC_SIZ 9U + +#ifndef CUSTOM_HID_HS_BINTERVAL +#define CUSTOM_HID_HS_BINTERVAL 0x05U +#endif /* CUSTOM_HID_HS_BINTERVAL */ + +#ifndef CUSTOM_HID_FS_BINTERVAL +#define CUSTOM_HID_FS_BINTERVAL 0x05U +#endif /* CUSTOM_HID_FS_BINTERVAL */ + +#ifndef USBD_CUSTOMHID_OUTREPORT_BUF_SIZE +#define USBD_CUSTOMHID_OUTREPORT_BUF_SIZE 0x02U +#endif /* USBD_CUSTOMHID_OUTREPORT_BUF_SIZE */ + +#ifndef USBD_CUSTOM_HID_REPORT_DESC_SIZE +#define USBD_CUSTOM_HID_REPORT_DESC_SIZE 33U +#endif /* USBD_CUSTOM_HID_REPORT_DESC_SIZE */ + +#define CUSTOM_HID_DESCRIPTOR_TYPE 0x21U +#define CUSTOM_HID_REPORT_DESC 0x22U + +#define CUSTOM_HID_REQ_SET_PROTOCOL 0x0BU +#define CUSTOM_HID_REQ_GET_PROTOCOL 0x03U + +#define CUSTOM_HID_REQ_SET_IDLE 0x0AU +#define CUSTOM_HID_REQ_GET_IDLE 0x02U + +#define CUSTOM_HID_REQ_SET_REPORT 0x09U +#define CUSTOM_HID_REQ_GET_REPORT 0x01U +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_TypesDefinitions + * @{ + */ +typedef enum +{ + CUSTOM_HID_IDLE = 0U, + CUSTOM_HID_BUSY, +} CUSTOM_HID_StateTypeDef; + +typedef struct _USBD_CUSTOM_HID_Itf +{ + uint8_t *pReport; + int8_t (*Init)(void); + int8_t (*DeInit)(void); + int8_t (*OutEvent)(uint8_t event_idx, uint8_t state); + +} USBD_CUSTOM_HID_ItfTypeDef; + +typedef struct +{ + uint8_t Report_buf[USBD_CUSTOMHID_OUTREPORT_BUF_SIZE]; + uint32_t Protocol; + uint32_t IdleState; + uint32_t AltSetting; + uint32_t IsReportAvailable; + CUSTOM_HID_StateTypeDef state; +} USBD_CUSTOM_HID_HandleTypeDef; +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_Variables + * @{ + */ + +extern USBD_ClassTypeDef USBD_HID_CUSTOM; + +extern uint8_t CUSTOM_HID_IN_EP; +extern uint8_t CUSTOM_HID_OUT_EP; +extern uint8_t CUSTOM_HID_ITF_NBR; +extern uint8_t CUSTOM_HID_STR_DESC_IDX; + +/** + * @} + */ + +/** @defgroup USB_CORE_Exported_Functions + * @{ + */ +uint8_t USBD_CUSTOM_HID_SendReport(USBD_HandleTypeDef *pdev, + uint8_t *report, uint16_t len); + +uint8_t USBD_CUSTOM_HID_ReceivePacket(USBD_HandleTypeDef *pdev); + +uint8_t USBD_CUSTOM_HID_RegisterInterface(USBD_HandleTypeDef *pdev, + USBD_CUSTOM_HID_ItfTypeDef *fops); + +void USBD_Update_HID_Custom_DESC(uint8_t *desc, uint8_t itf_no, uint8_t in_ep, uint8_t out_ep, uint8_t str_idx); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_CUSTOMHID_H */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/HID_CUSTOM/Src/usbd_hid_custom.c b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/HID_CUSTOM/Src/usbd_hid_custom.c new file mode 100644 index 0000000..f4d44d4 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/HID_CUSTOM/Src/usbd_hid_custom.c @@ -0,0 +1,797 @@ +/** + ****************************************************************************** + * @file usbd_customhid.c + * @author MCD Application Team + * @brief This file provides the CUSTOM_HID core functions. + * + * @verbatim + * + * =================================================================== + * CUSTOM_HID Class Description + * =================================================================== + * This module manages the CUSTOM_HID class V1.11 following the "Device Class Definition + * for Human Interface Devices (CUSTOM_HID) Version 1.11 Jun 27, 2001". + * This driver implements the following aspects of the specification: + * - The Boot Interface Subclass + * - Usage Page : Generic Desktop + * - Usage : Vendor + * - Collection : Application + * + * @note In HS mode and when the DMA is used, all variables and data structures + * dealing with the DMA during the transaction process should be 32-bit aligned. + * + * + * @endverbatim + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* BSPDependencies +- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" +- "stm32xxxxx_{eval}{discovery}_io.c" +EndBSPDependencies */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_hid_custom.h" +#include "usbd_ctlreq.h" + +#define _CUSTOM_HID_IN_EP 0x81U +#define _CUSTOM_HID_OUT_EP 0x01U +#define _CUSTOM_HID_ITF_NBR 0x00U +#define _CUSTOM_HID_STR_DESC_IDX 0x00U + +uint8_t CUSTOM_HID_IN_EP = _CUSTOM_HID_IN_EP; +uint8_t CUSTOM_HID_OUT_EP = _CUSTOM_HID_OUT_EP; +uint8_t CUSTOM_HID_ITF_NBR = _CUSTOM_HID_ITF_NBR; +uint8_t CUSTOM_HID_STR_DESC_IDX = _CUSTOM_HID_STR_DESC_IDX; + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_CUSTOM_HID + * @brief usbd core module + * @{ + */ + +/** @defgroup USBD_CUSTOM_HID_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_CUSTOM_HID_Private_Defines + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CUSTOM_HID_Private_Macros + * @{ + */ +/** + * @} + */ +/** @defgroup USBD_CUSTOM_HID_Private_FunctionPrototypes + * @{ + */ + +static uint8_t USBD_CUSTOM_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_CUSTOM_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_CUSTOM_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); + +static uint8_t USBD_CUSTOM_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum); +static uint8_t USBD_CUSTOM_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum); +static uint8_t USBD_CUSTOM_HID_EP0_RxReady(USBD_HandleTypeDef *pdev); + +static uint8_t *USBD_CUSTOM_HID_GetFSCfgDesc(uint16_t *length); +static uint8_t *USBD_CUSTOM_HID_GetHSCfgDesc(uint16_t *length); +static uint8_t *USBD_CUSTOM_HID_GetOtherSpeedCfgDesc(uint16_t *length); +static uint8_t *USBD_CUSTOM_HID_GetDeviceQualifierDesc(uint16_t *length); + +/** + * @} + */ + +/** @defgroup USBD_CUSTOM_HID_Private_Variables + * @{ + */ + +static USBD_CUSTOM_HID_HandleTypeDef CUSTOM_HID_Instance; + +USBD_ClassTypeDef USBD_HID_CUSTOM = + { + USBD_CUSTOM_HID_Init, + USBD_CUSTOM_HID_DeInit, + USBD_CUSTOM_HID_Setup, + NULL, /*EP0_TxSent*/ + USBD_CUSTOM_HID_EP0_RxReady, + /*EP0_RxReady*/ /* STATUS STAGE IN */ + USBD_CUSTOM_HID_DataIn, /*DataIn*/ + USBD_CUSTOM_HID_DataOut, + NULL, /*SOF */ + NULL, + NULL, + USBD_CUSTOM_HID_GetHSCfgDesc, + USBD_CUSTOM_HID_GetFSCfgDesc, + USBD_CUSTOM_HID_GetOtherSpeedCfgDesc, + USBD_CUSTOM_HID_GetDeviceQualifierDesc, +}; + +/* USB CUSTOM_HID device FS Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_CUSTOM_HID_CfgFSDesc[USB_CUSTOM_HID_CONFIG_DESC_SIZ] __ALIGN_END = + { + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_CUSTOM_HID_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */ + 0x00, + 0x01, /* bNumInterfaces: 1 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ +#if (USBD_SELF_POWERED == 1U) + 0xC0, /* bmAttributes: Bus Powered according to user configuration */ +#else + 0x80, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* MaxPower 100 mA: this current is used for detecting Vbus */ + + /************** Descriptor of CUSTOM HID interface ****************/ + /* 09 */ + 0x09, /* bLength: Interface Descriptor size*/ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ + _CUSTOM_HID_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints*/ + 0x03, /* bInterfaceClass: CUSTOM_HID */ + 0x00, /* bInterfaceSubClass : 1=BOOT, 0=no boot */ + 0x00, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */ + _CUSTOM_HID_STR_DESC_IDX, /* iInterface: Index of string descriptor */ + /******************** Descriptor of CUSTOM_HID *************************/ + /* 18 */ + 0x09, /* bLength: CUSTOM_HID Descriptor size */ + CUSTOM_HID_DESCRIPTOR_TYPE, /* bDescriptorType: CUSTOM_HID */ + 0x11, /* bCUSTOM_HIDUSTOM_HID: CUSTOM_HID Class Spec release number */ + 0x01, + 0x00, /* bCountryCode: Hardware target country */ + 0x01, /* bNumDescriptors: Number of CUSTOM_HID class descriptors to follow */ + 0x22, /* bDescriptorType */ + USBD_CUSTOM_HID_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */ + 0x00, + /******************** Descriptor of Custom HID endpoints ********************/ + /* 27 */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */ + _CUSTOM_HID_IN_EP, /* bEndpointAddress: Endpoint Address (IN) */ + 0x03, /* bmAttributes: Interrupt endpoint */ + CUSTOM_HID_EPIN_SIZE, /* wMaxPacketSize: 2 Byte max */ + 0x00, + CUSTOM_HID_FS_BINTERVAL, /* bInterval: Polling Interval */ + /* 34 */ + + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */ + _CUSTOM_HID_OUT_EP, /* bEndpointAddress: Endpoint Address (OUT) */ + 0x03, /* bmAttributes: Interrupt endpoint */ + CUSTOM_HID_EPOUT_SIZE, /* wMaxPacketSize: 2 Bytes max */ + 0x00, + CUSTOM_HID_FS_BINTERVAL, /* bInterval: Polling Interval */ + /* 41 */ +}; + +/* USB CUSTOM_HID device HS Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_CUSTOM_HID_CfgHSDesc[USB_CUSTOM_HID_CONFIG_DESC_SIZ] __ALIGN_END = + { + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_CUSTOM_HID_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */ + 0x00, + 0x01, /* bNumInterfaces: 1 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ +#if (USBD_SELF_POWERED == 1U) + 0xC0, /* bmAttributes: Bus Powered according to user configuration */ +#else + 0x80, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* MaxPower 100 mA: this current is used for detecting Vbus */ + + /************** Descriptor of CUSTOM HID interface ****************/ + /* 09 */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ + _CUSTOM_HID_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints */ + 0x03, /* bInterfaceClass: CUSTOM_HID */ + 0x00, /* bInterfaceSubClass : 1=BOOT, 0=no boot */ + 0x00, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */ + _CUSTOM_HID_STR_DESC_IDX, /* iInterface: Index of string descriptor */ + /******************** Descriptor of CUSTOM_HID *************************/ + /* 18 */ + 0x09, /* bLength: CUSTOM_HID Descriptor size */ + CUSTOM_HID_DESCRIPTOR_TYPE, /* bDescriptorType: CUSTOM_HID */ + 0x11, /* bCUSTOM_HIDUSTOM_HID: CUSTOM_HID Class Spec release number */ + 0x01, + 0x00, /* bCountryCode: Hardware target country */ + 0x01, /* bNumDescriptors: Number of CUSTOM_HID class descriptors to follow */ + 0x22, /* bDescriptorType */ + USBD_CUSTOM_HID_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */ + 0x00, + /******************** Descriptor of Custom HID endpoints ********************/ + /* 27 */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */ + _CUSTOM_HID_IN_EP, /* bEndpointAddress: Endpoint Address (IN) */ + 0x03, /* bmAttributes: Interrupt endpoint */ + CUSTOM_HID_EPIN_SIZE, /* wMaxPacketSize: 2 Byte max */ + 0x00, + CUSTOM_HID_HS_BINTERVAL, /* bInterval: Polling Interval */ + /* 34 */ + + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */ + _CUSTOM_HID_OUT_EP, /* bEndpointAddress: Endpoint Address (OUT) */ + 0x03, /* bmAttributes: Interrupt endpoint */ + CUSTOM_HID_EPOUT_SIZE, /* wMaxPacketSize: 2 Bytes max */ + 0x00, + CUSTOM_HID_HS_BINTERVAL, /* bInterval: Polling Interval */ + /* 41 */ +}; + +/* USB CUSTOM_HID device Other Speed Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_CUSTOM_HID_OtherSpeedCfgDesc[USB_CUSTOM_HID_CONFIG_DESC_SIZ] __ALIGN_END = + { + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_CUSTOM_HID_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */ + 0x00, + 0x01, /* bNumInterfaces: 1 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ +#if (USBD_SELF_POWERED == 1U) + 0xC0, /* bmAttributes: Bus Powered according to user configuration */ +#else + 0x80, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* MaxPower 100 mA: this current is used for detecting Vbus */ + + /************** Descriptor of CUSTOM HID interface ****************/ + /* 09 */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ + _CUSTOM_HID_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints */ + 0x03, /* bInterfaceClass: CUSTOM_HID */ + 0x00, /* bInterfaceSubClass : 1=BOOT, 0=no boot */ + 0x00, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */ + _CUSTOM_HID_STR_DESC_IDX, /* iInterface: Index of string descriptor */ + /******************** Descriptor of CUSTOM_HID *************************/ + /* 18 */ + 0x09, /* bLength: CUSTOM_HID Descriptor size */ + CUSTOM_HID_DESCRIPTOR_TYPE, /* bDescriptorType: CUSTOM_HID */ + 0x11, /* bCUSTOM_HIDUSTOM_HID: CUSTOM_HID Class Spec release number */ + 0x01, + 0x00, /* bCountryCode: Hardware target country */ + 0x01, /* bNumDescriptors: Number of CUSTOM_HID class descriptors to follow */ + 0x22, /* bDescriptorType */ + USBD_CUSTOM_HID_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */ + 0x00, + /******************** Descriptor of Custom HID endpoints ********************/ + /* 27 */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */ + _CUSTOM_HID_IN_EP, /* bEndpointAddress: Endpoint Address (IN) */ + 0x03, /* bmAttributes: Interrupt endpoint */ + CUSTOM_HID_EPIN_SIZE, /* wMaxPacketSize: 2 Bytes max */ + 0x00, + CUSTOM_HID_FS_BINTERVAL, /* bInterval: Polling Interval */ + /* 34 */ + + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */ + _CUSTOM_HID_OUT_EP, /* bEndpointAddress: Endpoint Address (OUT) */ + 0x03, /* bmAttributes: Interrupt endpoint */ + CUSTOM_HID_EPOUT_SIZE, /* wMaxPacketSize: 2 Bytes max */ + 0x00, + CUSTOM_HID_FS_BINTERVAL, /* bInterval: Polling Interval */ + /* 41 */ +}; + +/* USB CUSTOM_HID device Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_CUSTOM_HID_Desc[USB_CUSTOM_HID_DESC_SIZ] __ALIGN_END = + { + /* 18 */ + 0x09, /* bLength: CUSTOM_HID Descriptor size */ + CUSTOM_HID_DESCRIPTOR_TYPE, /* bDescriptorType: CUSTOM_HID */ + 0x11, /* bCUSTOM_HIDUSTOM_HID: CUSTOM_HID Class Spec release number */ + 0x01, + 0x00, /* bCountryCode: Hardware target country */ + 0x01, /* bNumDescriptors: Number of CUSTOM_HID class descriptors to follow */ + 0x22, /* bDescriptorType */ + USBD_CUSTOM_HID_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */ + 0x00, +}; + +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_CUSTOM_HID_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_CUSTOM_HID_Private_Functions + * @{ + */ + +/** + * @brief USBD_CUSTOM_HID_Init + * Initialize the CUSTOM_HID interface + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_CUSTOM_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(cfgidx); + USBD_CUSTOM_HID_HandleTypeDef *hhid; + + hhid = &CUSTOM_HID_Instance; + + if (hhid == NULL) + { + pdev->pClassData_HID_Custom = NULL; + return (uint8_t)USBD_EMEM; + } + + pdev->pClassData_HID_Custom = (void *)hhid; + + if (pdev->dev_speed == USBD_SPEED_HIGH) + { + pdev->ep_in[CUSTOM_HID_IN_EP & 0xFU].bInterval = CUSTOM_HID_HS_BINTERVAL; + pdev->ep_out[CUSTOM_HID_OUT_EP & 0xFU].bInterval = CUSTOM_HID_HS_BINTERVAL; + } + else /* LOW and FULL-speed endpoints */ + { + pdev->ep_in[CUSTOM_HID_IN_EP & 0xFU].bInterval = CUSTOM_HID_FS_BINTERVAL; + pdev->ep_out[CUSTOM_HID_OUT_EP & 0xFU].bInterval = CUSTOM_HID_FS_BINTERVAL; + } + + /* Open EP IN */ + (void)USBD_LL_OpenEP(pdev, CUSTOM_HID_IN_EP, USBD_EP_TYPE_INTR, + CUSTOM_HID_EPIN_SIZE); + + pdev->ep_in[CUSTOM_HID_IN_EP & 0xFU].is_used = 1U; + + /* Open EP OUT */ + (void)USBD_LL_OpenEP(pdev, CUSTOM_HID_OUT_EP, USBD_EP_TYPE_INTR, + CUSTOM_HID_EPOUT_SIZE); + + pdev->ep_out[CUSTOM_HID_OUT_EP & 0xFU].is_used = 1U; + + hhid->state = CUSTOM_HID_IDLE; + + ((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData_HID_Custom)->Init(); + + /* Prepare Out endpoint to receive 1st packet */ + (void)USBD_LL_PrepareReceive(pdev, CUSTOM_HID_OUT_EP, hhid->Report_buf, + USBD_CUSTOMHID_OUTREPORT_BUF_SIZE); + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CUSTOM_HID_Init + * DeInitialize the CUSTOM_HID layer + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_CUSTOM_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(cfgidx); + + /* Close CUSTOM_HID EP IN */ + (void)USBD_LL_CloseEP(pdev, CUSTOM_HID_IN_EP); + pdev->ep_in[CUSTOM_HID_IN_EP & 0xFU].is_used = 0U; + pdev->ep_in[CUSTOM_HID_IN_EP & 0xFU].bInterval = 0U; + + /* Close CUSTOM_HID EP OUT */ + (void)USBD_LL_CloseEP(pdev, CUSTOM_HID_OUT_EP); + pdev->ep_out[CUSTOM_HID_OUT_EP & 0xFU].is_used = 0U; + pdev->ep_out[CUSTOM_HID_OUT_EP & 0xFU].bInterval = 0U; + + /* Free allocated memory */ + if (pdev->pClassData_HID_Custom != NULL) + { + ((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData_HID_Custom)->DeInit(); +#if (0) + USBD_free(pdev->pClassData_HID_Custom); +#endif + pdev->pClassData_HID_Custom = NULL; + } + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CUSTOM_HID_Setup + * Handle the CUSTOM_HID specific requests + * @param pdev: instance + * @param req: usb requests + * @retval status + */ +static uint8_t USBD_CUSTOM_HID_Setup(USBD_HandleTypeDef *pdev, + USBD_SetupReqTypedef *req) +{ + USBD_CUSTOM_HID_HandleTypeDef *hhid = (USBD_CUSTOM_HID_HandleTypeDef *)pdev->pClassData_HID_Custom; + uint16_t len = 0U; + uint8_t *pbuf = NULL; + uint16_t status_info = 0U; + USBD_StatusTypeDef ret = USBD_OK; + + if (hhid == NULL) + { + return (uint8_t)USBD_FAIL; + } + + switch (req->bmRequest & USB_REQ_TYPE_MASK) + { + case USB_REQ_TYPE_CLASS: + switch (req->bRequest) + { + case CUSTOM_HID_REQ_SET_PROTOCOL: + hhid->Protocol = (uint8_t)(req->wValue); + break; + + case CUSTOM_HID_REQ_GET_PROTOCOL: + (void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->Protocol, 1U); + break; + + case CUSTOM_HID_REQ_SET_IDLE: + hhid->IdleState = (uint8_t)(req->wValue >> 8); + break; + + case CUSTOM_HID_REQ_GET_IDLE: + (void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->IdleState, 1U); + break; + + case CUSTOM_HID_REQ_SET_REPORT: + hhid->IsReportAvailable = 1U; + (void)USBD_CtlPrepareRx(pdev, hhid->Report_buf, req->wLength); + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + break; + + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) + { + case USB_REQ_GET_STATUS: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_GET_DESCRIPTOR: + if ((req->wValue >> 8) == CUSTOM_HID_REPORT_DESC) + { + len = MIN(USBD_CUSTOM_HID_REPORT_DESC_SIZE, req->wLength); + pbuf = ((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData_HID_Custom)->pReport; + } + else + { + if ((req->wValue >> 8) == CUSTOM_HID_DESCRIPTOR_TYPE) + { + pbuf = USBD_CUSTOM_HID_Desc; + len = MIN(USB_CUSTOM_HID_DESC_SIZ, req->wLength); + } + } + + (void)USBD_CtlSendData(pdev, pbuf, len); + break; + + case USB_REQ_GET_INTERFACE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->AltSetting, 1U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_SET_INTERFACE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + hhid->AltSetting = (uint8_t)(req->wValue); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_CLEAR_FEATURE: + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + return (uint8_t)ret; +} + +/** + * @brief USBD_CUSTOM_HID_SendReport + * Send CUSTOM_HID Report + * @param pdev: device instance + * @param buff: pointer to report + * @retval status + */ +uint8_t USBD_CUSTOM_HID_SendReport(USBD_HandleTypeDef *pdev, + uint8_t *report, uint16_t len) +{ + USBD_CUSTOM_HID_HandleTypeDef *hhid; + + if (pdev->pClassData_HID_Custom == NULL) + { + return (uint8_t)USBD_FAIL; + } + + hhid = (USBD_CUSTOM_HID_HandleTypeDef *)pdev->pClassData_HID_Custom; + + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + if (hhid->state == CUSTOM_HID_IDLE) + { + hhid->state = CUSTOM_HID_BUSY; + (void)USBD_LL_Transmit(pdev, CUSTOM_HID_IN_EP, report, len); + } + else + { + return (uint8_t)USBD_BUSY; + } + } + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CUSTOM_HID_GetFSCfgDesc + * return FS configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CUSTOM_HID_GetFSCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_CUSTOM_HID_CfgFSDesc); + + return USBD_CUSTOM_HID_CfgFSDesc; +} + +/** + * @brief USBD_CUSTOM_HID_GetHSCfgDesc + * return HS configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CUSTOM_HID_GetHSCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_CUSTOM_HID_CfgHSDesc); + + return USBD_CUSTOM_HID_CfgHSDesc; +} + +/** + * @brief USBD_CUSTOM_HID_GetOtherSpeedCfgDesc + * return other speed configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CUSTOM_HID_GetOtherSpeedCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_CUSTOM_HID_OtherSpeedCfgDesc); + + return USBD_CUSTOM_HID_OtherSpeedCfgDesc; +} + +/** + * @brief USBD_CUSTOM_HID_DataIn + * handle data IN Stage + * @param pdev: device instance + * @param epnum: endpoint index + * @retval status + */ +static uint8_t USBD_CUSTOM_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + UNUSED(epnum); + + /* Ensure that the FIFO is empty before a new transfer, this condition could + be caused by a new transfer before the end of the previous transfer */ + ((USBD_CUSTOM_HID_HandleTypeDef *)pdev->pClassData_HID_Custom)->state = CUSTOM_HID_IDLE; + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CUSTOM_HID_DataOut + * handle data OUT Stage + * @param pdev: device instance + * @param epnum: endpoint index + * @retval status + */ +static uint8_t USBD_CUSTOM_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + UNUSED(epnum); + USBD_CUSTOM_HID_HandleTypeDef *hhid; + + if (pdev->pClassData_HID_Custom == NULL) + { + return (uint8_t)USBD_FAIL; + } + + hhid = (USBD_CUSTOM_HID_HandleTypeDef *)pdev->pClassData_HID_Custom; + + /* USB data will be immediately processed, this allow next USB traffic being + NAKed till the end of the application processing */ + ((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData_HID_Custom)->OutEvent(hhid->Report_buf[0], hhid->Report_buf[1]); + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CUSTOM_HID_ReceivePacket + * prepare OUT Endpoint for reception + * @param pdev: device instance + * @retval status + */ +uint8_t USBD_CUSTOM_HID_ReceivePacket(USBD_HandleTypeDef *pdev) +{ + USBD_CUSTOM_HID_HandleTypeDef *hhid; + + if (pdev->pClassData_HID_Custom == NULL) + { + return (uint8_t)USBD_FAIL; + } + + hhid = (USBD_CUSTOM_HID_HandleTypeDef *)pdev->pClassData_HID_Custom; + + /* Resume USB Out process */ + (void)USBD_LL_PrepareReceive(pdev, CUSTOM_HID_OUT_EP, hhid->Report_buf, + USBD_CUSTOMHID_OUTREPORT_BUF_SIZE); + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_CUSTOM_HID_EP0_RxReady + * Handles control request data. + * @param pdev: device instance + * @retval status + */ +static uint8_t USBD_CUSTOM_HID_EP0_RxReady(USBD_HandleTypeDef *pdev) +{ + USBD_CUSTOM_HID_HandleTypeDef *hhid = (USBD_CUSTOM_HID_HandleTypeDef *)pdev->pClassData_HID_Custom; + + if (hhid == NULL) + { + return (uint8_t)USBD_FAIL; + } + + if (hhid->IsReportAvailable == 1U) + { + ((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData_HID_Custom)->OutEvent(hhid->Report_buf[0], hhid->Report_buf[1]); + hhid->IsReportAvailable = 0U; + } + + return (uint8_t)USBD_OK; +} + +/** + * @brief DeviceQualifierDescriptor + * return Device Qualifier descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CUSTOM_HID_GetDeviceQualifierDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_CUSTOM_HID_DeviceQualifierDesc); + + return USBD_CUSTOM_HID_DeviceQualifierDesc; +} + +/** + * @brief USBD_CUSTOM_HID_RegisterInterface + * @param pdev: device instance + * @param fops: CUSTOMHID Interface callback + * @retval status + */ +uint8_t USBD_CUSTOM_HID_RegisterInterface(USBD_HandleTypeDef *pdev, + USBD_CUSTOM_HID_ItfTypeDef *fops) +{ + if (fops == NULL) + { + return (uint8_t)USBD_FAIL; + } + + pdev->pUserData_HID_Custom = fops; + + return (uint8_t)USBD_OK; +} + +void USBD_Update_HID_Custom_DESC(uint8_t *desc, uint8_t itf_no, uint8_t in_ep, uint8_t out_ep, uint8_t str_idx) +{ + desc[11] = itf_no; + desc[17] = str_idx; + desc[29] = in_ep; + desc[36] = out_ep; + + CUSTOM_HID_IN_EP = in_ep; + CUSTOM_HID_OUT_EP = out_ep; + CUSTOM_HID_ITF_NBR = itf_no; + CUSTOM_HID_STR_DESC_IDX = str_idx; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/HID_KEYBOARD/Inc/usbd_hid_keyboard.h b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/HID_KEYBOARD/Inc/usbd_hid_keyboard.h new file mode 100644 index 0000000..2d3c9ef --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/HID_KEYBOARD/Inc/usbd_hid_keyboard.h @@ -0,0 +1,144 @@ +/** + ****************************************************************************** + * @file usbd_hid.h + * @author MCD Application Team + * @brief Header file for the usbd_hid_core.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_HID_KEYBAORD_H +#define __USB_HID_KEYBAORD_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ioreq.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_HID + * @brief This file is the Header file for usbd_hid.c + * @{ + */ + + +/** @defgroup USBD_HID_Exported_Defines + * @{ + */ + +#define HID_KEYBOARD_STR_DESC "STM32 USB KEYBOARD" + +#define HID_KEYBOARD_EPIN_SIZE 0x08U + +#define HID_KEYBOARD_CONFIG_DESC_SIZE 34U +#define HID_KEYBOARD_DESC_SIZE 9U + +#define HID_KEYBOARD_REPORT_DESC_SIZE 187U + +#define HID_KEYBOARD_DESCRIPTOR_TYPE 0x21U +#define HID_KEYBOARD_REPORT_DESC 0x22U + +#ifndef HID_KEYBOARD_HS_BINTERVAL +#define HID_KEYBOARD_HS_BINTERVAL 0x07U +#endif /* HID_KEYBOARD_HS_BINTERVAL */ + +#ifndef HID_KEYBOARD_FS_BINTERVAL +#define HID_KEYBOARD_FS_BINTERVAL 0x0AU +#endif /* HID_KEYBOARD_FS_BINTERVAL */ + +#define HID_KEYBOARD_REQ_SET_PROTOCOL 0x0BU +#define HID_KEYBOARD_REQ_GET_PROTOCOL 0x03U + +#define HID_KEYBOARD_REQ_SET_IDLE 0x0AU +#define HID_KEYBOARD_REQ_GET_IDLE 0x02U + +#define HID_KEYBOARD_REQ_SET_REPORT 0x09U +#define HID_KEYBOARD_REQ_GET_REPORT 0x01U +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_TypesDefinitions + * @{ + */ +typedef enum +{ + KEYBOARD_HID_IDLE = 0, + KEYBOARD_HID_BUSY, +} HID_Keyboard_StateTypeDef; + +typedef struct +{ + uint32_t Protocol; + uint32_t IdleState; + uint32_t AltSetting; + HID_Keyboard_StateTypeDef state; +} USBD_HID_Keyboard_HandleTypeDef; +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_Variables + * @{ + */ + +extern USBD_ClassTypeDef USBD_HID_KEYBOARD; + +extern uint8_t HID_KEYBOARD_IN_EP; +extern uint8_t HID_KEYBOARD_ITF_NBR; +extern uint8_t HID_KEYBOARD_STR_DESC_IDX; + +/** + * @} + */ + +/** @defgroup USB_CORE_Exported_Functions + * @{ + */ +uint8_t USBD_HID_Keybaord_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len); +uint32_t USBD_HID_Keyboard_GetPollingInterval(USBD_HandleTypeDef *pdev); + +void USBD_Update_HID_KBD_DESC(uint8_t *desc, uint8_t itf_no, uint8_t in_ep, uint8_t str_idx); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_HID_KEYBAORD_H */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/HID_KEYBOARD/Src/usbd_hid_keyboard.c b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/HID_KEYBOARD/Src/usbd_hid_keyboard.c new file mode 100644 index 0000000..9500cc9 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/HID_KEYBOARD/Src/usbd_hid_keyboard.c @@ -0,0 +1,713 @@ +/** + ****************************************************************************** + * @file usbd_hid.c + * @author MCD Application Team + * @brief This file provides the HID core functions. + * + * @verbatim + * + * =================================================================== + * HID Class Description + * =================================================================== + * This module manages the HID class V1.11 following the "Device Class Definition + * for Human Interface Devices (HID) Version 1.11 Jun 27, 2001". + * This driver implements the following aspects of the specification: + * - The Boot Interface Subclass + * - The Keyboard protocol + * - Usage Page : Generic Desktop + * - Collection : Application + * + * @note In HS mode and when the DMA is used, all variables and data structures + * dealing with the DMA during the transaction process should be 32-bit aligned. + * + * + * @endverbatim + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* BSPDependencies +- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" +- "stm32xxxxx_{eval}{discovery}_io.c" +EndBSPDependencies */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_hid_keyboard.h" +#include "usbd_ctlreq.h" + +#define _HID_KEYBOARD_IN_EP 0x81U +#define _HID_KEYBOARD_ITF_NBR 0x00 +#define _HID_KEYBOARD_STR_DESC_IDX 0x00U + +uint8_t HID_KEYBOARD_IN_EP = _HID_KEYBOARD_IN_EP; +uint8_t HID_KEYBOARD_ITF_NBR = _HID_KEYBOARD_ITF_NBR; +uint8_t HID_KEYBOARD_STR_DESC_IDX = _HID_KEYBOARD_STR_DESC_IDX; + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_HID + * @brief usbd core module + * @{ + */ + +/** @defgroup USBD_HID_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_HID_Private_Defines + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_HID_Private_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_HID_Private_FunctionPrototypes + * @{ + */ + +static uint8_t USBD_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static uint8_t USBD_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum); + +static uint8_t *USBD_HID_GetFSCfgDesc(uint16_t *length); +static uint8_t *USBD_HID_GetHSCfgDesc(uint16_t *length); +static uint8_t *USBD_HID_GetOtherSpeedCfgDesc(uint16_t *length); +static uint8_t *USBD_HID_GetDeviceQualifierDesc(uint16_t *length); + +/** + * @} + */ + +/** @defgroup USBD_HID_Private_Variables + * @{ + */ + +static USBD_HID_Keyboard_HandleTypeDef USBD_HID_KBD_Instace; + +USBD_ClassTypeDef USBD_HID_KEYBOARD = + { + USBD_HID_Init, + USBD_HID_DeInit, + USBD_HID_Setup, + NULL, /* EP0_TxSent */ + NULL, /* EP0_RxReady */ + USBD_HID_DataIn, /* DataIn */ + NULL, /* DataOut */ + NULL, /* SOF */ + NULL, + NULL, + USBD_HID_GetHSCfgDesc, + USBD_HID_GetFSCfgDesc, + USBD_HID_GetOtherSpeedCfgDesc, + USBD_HID_GetDeviceQualifierDesc, +}; + +/* USB HID device FS Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_HID_KEYBOARD_CfgFSDesc[HID_KEYBOARD_CONFIG_DESC_SIZE] __ALIGN_END = + { + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + HID_KEYBOARD_CONFIG_DESC_SIZE, /* wTotalLength: Bytes returned */ + 0x00, + 0x01, /* bNumInterfaces: 1 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ +#if (USBD_SELF_POWERED == 1U) + 0xE0, /* bmAttributes: Bus Powered according to user configuration */ +#else + 0xA0, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* MaxPower 100 mA: this current is used for detecting Vbus */ + + /************** Descriptor of Keyboard interface ****************/ + /* 09 */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ + _HID_KEYBOARD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints */ + 0x03, /* bInterfaceClass: HID */ + 0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */ + 0x01, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */ + _HID_KEYBOARD_STR_DESC_IDX, /* iInterface: Index of string descriptor */ + /******************** Descriptor of Keyboard HID ********************/ + /* 18 */ + 0x09, /* bLength: HID Descriptor size */ + HID_KEYBOARD_DESCRIPTOR_TYPE, /* bDescriptorType: HID */ + 0x11, /* bcdHID: HID Class Spec release number */ + 0x01, + 0x00, /* bCountryCode: Hardware target country */ + 0x01, /* bNumDescriptors: Number of HID class descriptors to follow */ + 0x22, /* bDescriptorType */ + HID_KEYBOARD_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */ + 0x00, + /******************** Descriptor of Keyboard endpoint ********************/ + /* 27 */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType:*/ + _HID_KEYBOARD_IN_EP, /* bEndpointAddress: Endpoint Address (IN) */ + 0x03, /* bmAttributes: Interrupt endpoint */ + HID_KEYBOARD_EPIN_SIZE, /* wMaxPacketSize: 4 Byte max */ + 0x00, + HID_KEYBOARD_FS_BINTERVAL, /* bInterval: Polling Interval */ + /* 34 */ +}; + +/* USB HID device HS Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_HID_KEYBOARD_CfgHSDesc[HID_KEYBOARD_CONFIG_DESC_SIZE] __ALIGN_END = + { + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + HID_KEYBOARD_CONFIG_DESC_SIZE, /* wTotalLength: Bytes returned */ + 0x00, + 0x01, /* bNumInterfaces: 1 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ +#if (USBD_SELF_POWERED == 1U) + 0xE0, /* bmAttributes: Bus Powered according to user configuration */ +#else + 0xA0, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* MaxPower 100 mA: this current is used for detecting Vbus */ + + /************** Descriptor of Keyboard interface ****************/ + /* 09 */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ + _HID_KEYBOARD_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints */ + 0x03, /* bInterfaceClass: HID */ + 0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */ + 0x01, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */ + _HID_KEYBOARD_STR_DESC_IDX, /* iInterface: Index of string descriptor */ + /******************** Descriptor of Keyboard HID ********************/ + /* 18 */ + 0x09, /* bLength: HID Descriptor size */ + HID_KEYBOARD_DESCRIPTOR_TYPE, /* bDescriptorType: HID */ + 0x11, /* bcdHID: HID Class Spec release number */ + 0x01, + 0x00, /* bCountryCode: Hardware target country */ + 0x01, /* bNumDescriptors: Number of HID class descriptors to follow */ + 0x22, /* bDescriptorType */ + HID_KEYBOARD_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */ + 0x00, + /******************** Descriptor of Keyboard endpoint ********************/ + /* 27 */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */ + _HID_KEYBOARD_IN_EP, /* bEndpointAddress: Endpoint Address (IN) */ + 0x03, /* bmAttributes: Interrupt endpoint */ + HID_KEYBOARD_EPIN_SIZE, /* wMaxPacketSize: 4 Byte max */ + 0x00, + HID_KEYBOARD_HS_BINTERVAL, /* bInterval: Polling Interval */ + /* 34 */ +}; + +/* USB HID device Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_HID_KEYBOARD_Desc[HID_KEYBOARD_DESC_SIZE] __ALIGN_END = + { + /* 18 */ + 0x09, /* bLength: HID Descriptor size */ + HID_KEYBOARD_DESCRIPTOR_TYPE, /* bDescriptorType: HID */ + 0x11, /* bcdHID: HID Class Spec release number */ + 0x01, + 0x00, /* bCountryCode: Hardware target country */ + 0x01, /* bNumDescriptors: Number of HID class descriptors to follow */ + 0x22, /* bDescriptorType */ + HID_KEYBOARD_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */ + 0x00, +}; + +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_HID_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, +}; + +/* HID keyboard report descriptor */ +__ALIGN_BEGIN static uint8_t HID_KEYBOARD_ReportDesc[HID_KEYBOARD_REPORT_DESC_SIZE] __ALIGN_END = + { + 0x05, 0x01, + 0x09, 0x06, + 0xA1, 0x01, + 0x85, 0x01, + 0x05, 0x07, + 0x19, 0xE0, + 0x29, 0xE7, + 0x15, 0x00, + 0x25, 0x01, + 0x75, 0x01, + 0x95, 0x08, + 0x81, 0x02, + 0x75, 0x08, + 0x95, 0x01, + 0x81, 0x01, + 0x05, 0x07, + 0x19, 0x00, + 0x29, 0x65, + 0x15, 0x00, + 0x25, 0x65, + 0x75, 0x08, + 0x95, 0x05, + 0x81, 0x00, + 0xC0, 0x05, + 0x0C, 0x09, + 0x01, 0xA1, + 0x01, 0x85, + 0x02, 0x19, + 0x00, 0x2A, + 0x3C, 0x02, + 0x15, 0x00, + 0x26, 0x3C, + 0x02, 0x95, + 0x01, 0x75, + 0x10, 0x81, + 0x00, 0xC0, + 0x05, 0x01, + 0x09, 0x80, + 0xA1, 0x01, + 0x85, 0x03, + 0x19, 0x81, + 0x29, 0x83, + 0x15, 0x00, + 0x25, 0x01, + 0x75, 0x01, + 0x95, 0x03, + 0x81, 0x02, + 0x95, 0x05, + 0x81, 0x01, + 0xC0, 0x06, + 0x01, 0xFF, + 0x09, 0x01, + 0xA1, 0x01, + 0x85, 0x04, + 0x95, 0x01, + 0x75, 0x08, + 0x15, 0x01, + 0x25, 0x0A, + 0x09, 0x20, + 0xB1, 0x03, + 0x09, 0x23, + 0xB1, 0x03, + 0x25, 0x4F, + 0x09, 0x21, + 0xB1, 0x03, + 0x25, 0x30, + 0x09, 0x22, + 0xB1, 0x03, + 0x95, 0x03, + 0x09, 0x24, + 0xB1, 0x03, + 0xC0, 0x06, + 0x01, 0xFF, + 0x09, 0x01, + 0xA1, 0x01, + 0x85, 0x05, + 0x95, 0x01, + 0x75, 0x08, + 0x15, 0x01, + 0x25, 0x0A, + 0x09, 0x20, + 0xB1, 0x03, + 0x09, 0x23, + 0xB1, 0x03, + 0x25, 0x4F, + 0x09, 0x21, + 0xB1, 0x03, + 0x25, 0x30, + 0x09, 0x22, + 0xB1, 0x03, + 0x95, 0x03, + 0x09, 0x24, + 0xB1, 0x03, + 0xC0}; + +/** + * @} + */ + +/** @defgroup USBD_HID_Private_Functions + * @{ + */ + +/** + * @brief USBD_HID_Init + * Initialize the HID interface + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(cfgidx); + + USBD_HID_Keyboard_HandleTypeDef *hhid; + + hhid = &USBD_HID_KBD_Instace; + + if (hhid == NULL) + { + pdev->pClassData_HID_Keyboard = NULL; + return (uint8_t)USBD_EMEM; + } + + pdev->pClassData_HID_Keyboard = (void *)hhid; + + if (pdev->dev_speed == USBD_SPEED_HIGH) + { + pdev->ep_in[HID_KEYBOARD_IN_EP & 0xFU].bInterval = HID_KEYBOARD_HS_BINTERVAL; + } + else /* LOW and FULL-speed endpoints */ + { + pdev->ep_in[HID_KEYBOARD_IN_EP & 0xFU].bInterval = HID_KEYBOARD_FS_BINTERVAL; + } + + /* Open EP IN */ + (void)USBD_LL_OpenEP(pdev, HID_KEYBOARD_IN_EP, USBD_EP_TYPE_INTR, HID_KEYBOARD_EPIN_SIZE); + pdev->ep_in[HID_KEYBOARD_IN_EP & 0xFU].is_used = 1U; + + hhid->state = KEYBOARD_HID_IDLE; + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_HID_DeInit + * DeInitialize the HID layer + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(cfgidx); + + /* Close HID EPs */ + (void)USBD_LL_CloseEP(pdev, HID_KEYBOARD_IN_EP); + pdev->ep_in[HID_KEYBOARD_IN_EP & 0xFU].is_used = 0U; + pdev->ep_in[HID_KEYBOARD_IN_EP & 0xFU].bInterval = 0U; + + /* Free allocated memory */ + if (pdev->pClassData_HID_Keyboard != NULL) + { +#if (0) + (void)USBD_free(pdev->pClassData_HID_Keyboard); +#endif + pdev->pClassData_HID_Keyboard = NULL; + } + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_HID_Setup + * Handle the HID specific requests + * @param pdev: instance + * @param req: usb requests + * @retval status + */ +static uint8_t USBD_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassData_HID_Keyboard; + USBD_StatusTypeDef ret = USBD_OK; + uint16_t len; + uint8_t *pbuf; + uint16_t status_info = 0U; + + if (hhid == NULL) + { + return (uint8_t)USBD_FAIL; + } + + switch (req->bmRequest & USB_REQ_TYPE_MASK) + { + case USB_REQ_TYPE_CLASS: + switch (req->bRequest) + { + case HID_KEYBOARD_REQ_SET_PROTOCOL: + hhid->Protocol = (uint8_t)(req->wValue); + break; + + case HID_KEYBOARD_REQ_GET_PROTOCOL: + (void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->Protocol, 1U); + break; + + case HID_KEYBOARD_REQ_SET_IDLE: + hhid->IdleState = (uint8_t)(req->wValue >> 8); + break; + + case HID_KEYBOARD_REQ_GET_IDLE: + (void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->IdleState, 1U); + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + break; + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) + { + case USB_REQ_GET_STATUS: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_GET_DESCRIPTOR: + if ((req->wValue >> 8) == HID_KEYBOARD_REPORT_DESC) + { + len = MIN(HID_KEYBOARD_REPORT_DESC_SIZE, req->wLength); + pbuf = HID_KEYBOARD_ReportDesc; + } + else if ((req->wValue >> 8) == HID_KEYBOARD_DESCRIPTOR_TYPE) + { + pbuf = USBD_HID_KEYBOARD_Desc; + len = MIN(HID_KEYBOARD_DESC_SIZE, req->wLength); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + (void)USBD_CtlSendData(pdev, pbuf, len); + break; + + case USB_REQ_GET_INTERFACE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->AltSetting, 1U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_SET_INTERFACE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + hhid->AltSetting = (uint8_t)(req->wValue); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_CLEAR_FEATURE: + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + + return (uint8_t)ret; +} + +/** + * @brief USBD_HID_GetCfgFSDesc + * return FS configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_HID_GetFSCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_HID_KEYBOARD_CfgFSDesc); + + return USBD_HID_KEYBOARD_CfgFSDesc; +} + +/** + * @brief USBD_HID_GetCfgHSDesc + * return HS configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_HID_GetHSCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_HID_KEYBOARD_CfgHSDesc); + + return USBD_HID_KEYBOARD_CfgHSDesc; +} + +/** + * @brief USBD_HID_GetOtherSpeedCfgDesc + * return other speed configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_HID_GetOtherSpeedCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_HID_KEYBOARD_CfgFSDesc); + + return USBD_HID_KEYBOARD_CfgFSDesc; +} + +/** + * @brief USBD_HID_DataIn + * handle data IN Stage + * @param pdev: device instance + * @param epnum: endpoint index + * @retval status + */ +static uint8_t USBD_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + UNUSED(epnum); + /* Ensure that the FIFO is empty before a new transfer, this condition could + be caused by a new transfer before the end of the previous transfer */ + ((USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassData_HID_Keyboard)->state = KEYBOARD_HID_IDLE; + + return (uint8_t)USBD_OK; +} + +/** + * @brief DeviceQualifierDescriptor + * return Device Qualifier descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_HID_GetDeviceQualifierDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_HID_DeviceQualifierDesc); + + return USBD_HID_DeviceQualifierDesc; +} + +/** + * @brief USBD_HID_SendReport + * Send HID Report + * @param pdev: device instance + * @param buff: pointer to report + * @retval status + */ +uint8_t USBD_HID_Keybaord_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len) +{ + USBD_HID_Keyboard_HandleTypeDef *hhid = (USBD_HID_Keyboard_HandleTypeDef *)pdev->pClassData_HID_Keyboard; + + if (hhid == NULL) + { + return (uint8_t)USBD_FAIL; + } + + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + if (hhid->state == KEYBOARD_HID_IDLE) + { + hhid->state = KEYBOARD_HID_BUSY; + (void)USBD_LL_Transmit(pdev, HID_KEYBOARD_IN_EP, report, len); + } + } + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_HID_GetPollingInterval + * return polling interval from endpoint descriptor + * @param pdev: device instance + * @retval polling interval + */ +uint32_t USBD_HID_Keyboard_GetPollingInterval(USBD_HandleTypeDef *pdev) +{ + uint32_t polling_interval; + + /* HIGH-speed endpoints */ + if (pdev->dev_speed == USBD_SPEED_HIGH) + { + /* Sets the data transfer polling interval for high speed transfers. + Values between 1..16 are allowed. Values correspond to interval + of 2 ^ (bInterval-1). This option (8 ms, corresponds to HID_HS_BINTERVAL */ + polling_interval = (((1U << (HID_KEYBOARD_HS_BINTERVAL - 1U))) / 8U); + } + else /* LOW and FULL-speed endpoints */ + { + /* Sets the data transfer polling interval for low and full + speed transfers */ + polling_interval = HID_KEYBOARD_FS_BINTERVAL; + } + + return ((uint32_t)(polling_interval)); +} + +void USBD_Update_HID_KBD_DESC(uint8_t *desc, uint8_t itf_no, uint8_t in_ep, uint8_t str_idx) +{ + desc[11] = itf_no; + desc[17] = str_idx; + desc[29] = in_ep; + + HID_KEYBOARD_IN_EP = in_ep; + HID_KEYBOARD_ITF_NBR = itf_no; + HID_KEYBOARD_STR_DESC_IDX = str_idx; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/HID_MOUSE/Inc/usbd_hid_mouse.h b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/HID_MOUSE/Inc/usbd_hid_mouse.h new file mode 100644 index 0000000..9cfae3d --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/HID_MOUSE/Inc/usbd_hid_mouse.h @@ -0,0 +1,142 @@ +/** + ****************************************************************************** + * @file usbd_hid.h + * @author MCD Application Team + * @brief Header file for the usbd_hid_core.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_HID_H +#define __USB_HID_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ioreq.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_HID + * @brief This file is the Header file for usbd_hid.c + * @{ + */ + + +/** @defgroup USBD_HID_Exported_Defines + * @{ + */ +#define HID_MOUSE_STR_DESC "STM32 USB MOUSE" + +#define HID_EPIN_SIZE 0x04U + +#define USB_HID_CONFIG_DESC_SIZ 34U +#define USB_HID_DESC_SIZ 9U +#define HID_MOUSE_REPORT_DESC_SIZE 74U + +#define HID_DESCRIPTOR_TYPE 0x21U +#define HID_REPORT_DESC 0x22U + +#ifndef HID_HS_BINTERVAL +#define HID_HS_BINTERVAL 0x07U +#endif /* HID_HS_BINTERVAL */ + +#ifndef HID_FS_BINTERVAL +#define HID_FS_BINTERVAL 0x0AU +#endif /* HID_FS_BINTERVAL */ + +#define HID_REQ_SET_PROTOCOL 0x0BU +#define HID_REQ_GET_PROTOCOL 0x03U + +#define HID_REQ_SET_IDLE 0x0AU +#define HID_REQ_GET_IDLE 0x02U + +#define HID_REQ_SET_REPORT 0x09U +#define HID_REQ_GET_REPORT 0x01U +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_TypesDefinitions + * @{ + */ +typedef enum +{ + HID_IDLE = 0, + HID_BUSY, +} HID_StateTypeDef; + +typedef struct +{ + uint32_t Protocol; + uint32_t IdleState; + uint32_t AltSetting; + HID_StateTypeDef state; +} USBD_HID_HandleTypeDef; +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_Variables + * @{ + */ + +extern USBD_ClassTypeDef USBD_HID_MOUSE; + +extern uint8_t HID_MOUSE_IN_EP; +extern uint8_t HID_MOUSE_ITF_NBR; +extern uint8_t HID_MOUSE_STR_DESC_IDX; + +/** + * @} + */ + +/** @defgroup USB_CORE_Exported_Functions + * @{ + */ +uint8_t USBD_HID_Mouse_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len); +uint32_t USBD_HID_Mouse_GetPollingInterval(USBD_HandleTypeDef *pdev); + +void USBD_Update_HID_Mouse_DESC(uint8_t *desc, uint8_t itf_no, uint8_t in_ep, uint8_t str_idx); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_HID_H */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/HID_MOUSE/Src/usbd_hid_mouse.c b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/HID_MOUSE/Src/usbd_hid_mouse.c new file mode 100644 index 0000000..a028e72 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/HID_MOUSE/Src/usbd_hid_mouse.c @@ -0,0 +1,665 @@ +/** + ****************************************************************************** + * @file usbd_hid.c + * @author MCD Application Team + * @brief This file provides the HID core functions. + * + * @verbatim + * + * =================================================================== + * HID Class Description + * =================================================================== + * This module manages the HID class V1.11 following the "Device Class Definition + * for Human Interface Devices (HID) Version 1.11 Jun 27, 2001". + * This driver implements the following aspects of the specification: + * - The Boot Interface Subclass + * - The Mouse protocol + * - Usage Page : Generic Desktop + * - Usage : Joystick + * - Collection : Application + * + * @note In HS mode and when the DMA is used, all variables and data structures + * dealing with the DMA during the transaction process should be 32-bit aligned. + * + * + * @endverbatim + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* BSPDependencies +- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" +- "stm32xxxxx_{eval}{discovery}_io.c" +EndBSPDependencies */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_hid_mouse.h" +#include "usbd_ctlreq.h" + +#define _HID_MOUSE_IN_EP 0x81U +#define _HID_MOUSE_ITF_NBR 0x00 +#define _HID_MOUSE_STR_DESC_IDX 0x00U + +uint8_t HID_MOUSE_IN_EP = _HID_MOUSE_IN_EP; +uint8_t HID_MOUSE_ITF_NBR = _HID_MOUSE_ITF_NBR; +uint8_t HID_MOUSE_STR_DESC_IDX = _HID_MOUSE_STR_DESC_IDX; + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_HID + * @brief usbd core module + * @{ + */ + +/** @defgroup USBD_HID_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_HID_Private_Defines + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_HID_Private_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_HID_Private_FunctionPrototypes + * @{ + */ + +static uint8_t USBD_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static uint8_t USBD_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum); + +static uint8_t *USBD_HID_GetFSCfgDesc(uint16_t *length); +static uint8_t *USBD_HID_GetHSCfgDesc(uint16_t *length); +static uint8_t *USBD_HID_GetOtherSpeedCfgDesc(uint16_t *length); +static uint8_t *USBD_HID_GetDeviceQualifierDesc(uint16_t *length); + +/** + * @} + */ + +/** @defgroup USBD_HID_Private_Variables + * @{ + */ + +static USBD_HID_HandleTypeDef USBD_HID_Instance; + +USBD_ClassTypeDef USBD_HID_MOUSE = + { + USBD_HID_Init, + USBD_HID_DeInit, + USBD_HID_Setup, + NULL, /* EP0_TxSent */ + NULL, /* EP0_RxReady */ + USBD_HID_DataIn, /* DataIn */ + NULL, /* DataOut */ + NULL, /* SOF */ + NULL, + NULL, + USBD_HID_GetHSCfgDesc, + USBD_HID_GetFSCfgDesc, + USBD_HID_GetOtherSpeedCfgDesc, + USBD_HID_GetDeviceQualifierDesc, +}; + +/* USB HID device FS Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_HID_CfgFSDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END = + { + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_HID_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */ + 0x00, + 0x01, /* bNumInterfaces: 1 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ +#if (USBD_SELF_POWERED == 1U) + 0xE0, /* bmAttributes: Bus Powered according to user configuration */ +#else + 0xA0, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* MaxPower 100 mA: this current is used for detecting Vbus */ + + /************** Descriptor of Joystick Mouse interface ****************/ + /* 09 */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ + _HID_MOUSE_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints */ + 0x03, /* bInterfaceClass: HID */ + 0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */ + 0x02, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */ + _HID_MOUSE_STR_DESC_IDX, /* iInterface: Index of string descriptor */ + /******************** Descriptor of Joystick Mouse HID ********************/ + /* 18 */ + 0x09, /* bLength: HID Descriptor size */ + HID_DESCRIPTOR_TYPE, /* bDescriptorType: HID */ + 0x11, /* bcdHID: HID Class Spec release number */ + 0x01, + 0x00, /* bCountryCode: Hardware target country */ + 0x01, /* bNumDescriptors: Number of HID class descriptors to follow */ + 0x22, /* bDescriptorType */ + HID_MOUSE_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */ + 0x00, + /******************** Descriptor of Mouse endpoint ********************/ + /* 27 */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType:*/ + _HID_MOUSE_IN_EP, /* bEndpointAddress: Endpoint Address (IN) */ + 0x03, /* bmAttributes: Interrupt endpoint */ + HID_EPIN_SIZE, /* wMaxPacketSize: 4 Byte max */ + 0x00, + HID_FS_BINTERVAL, /* bInterval: Polling Interval */ + /* 34 */ +}; + +/* USB HID device HS Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_HID_CfgHSDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END = + { + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_HID_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */ + 0x00, + 0x01, /* bNumInterfaces: 1 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ +#if (USBD_SELF_POWERED == 1U) + 0xE0, /* bmAttributes: Bus Powered according to user configuration */ +#else + 0xA0, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* MaxPower 100 mA: this current is used for detecting Vbus */ + + /************** Descriptor of Joystick Mouse interface ****************/ + /* 09 */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ + _HID_MOUSE_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints */ + 0x03, /* bInterfaceClass: HID */ + 0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */ + 0x02, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */ + _HID_MOUSE_STR_DESC_IDX, /* iInterface: Index of string descriptor */ + /******************** Descriptor of Joystick Mouse HID ********************/ + /* 18 */ + 0x09, /* bLength: HID Descriptor size */ + HID_DESCRIPTOR_TYPE, /* bDescriptorType: HID */ + 0x11, /* bcdHID: HID Class Spec release number */ + 0x01, + 0x00, /* bCountryCode: Hardware target country */ + 0x01, /* bNumDescriptors: Number of HID class descriptors to follow */ + 0x22, /* bDescriptorType */ + HID_MOUSE_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */ + 0x00, + /******************** Descriptor of Mouse endpoint ********************/ + /* 27 */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */ + _HID_MOUSE_IN_EP, /* bEndpointAddress: Endpoint Address (IN) */ + 0x03, /* bmAttributes: Interrupt endpoint */ + HID_EPIN_SIZE, /* wMaxPacketSize: 4 Byte max */ + 0x00, + HID_HS_BINTERVAL, /* bInterval: Polling Interval */ + /* 34 */ +}; + +/* USB HID device Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_HID_Desc[USB_HID_DESC_SIZ] __ALIGN_END = + { + /* 18 */ + 0x09, /* bLength: HID Descriptor size */ + HID_DESCRIPTOR_TYPE, /* bDescriptorType: HID */ + 0x11, /* bcdHID: HID Class Spec release number */ + 0x01, + 0x00, /* bCountryCode: Hardware target country */ + 0x01, /* bNumDescriptors: Number of HID class descriptors to follow */ + 0x22, /* bDescriptorType */ + HID_MOUSE_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */ + 0x00, +}; + +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_HID_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, +}; + +__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END = + { + 0x05, 0x01, + 0x09, 0x02, + 0xA1, 0x01, + 0x09, 0x01, + + 0xA1, 0x00, + 0x05, 0x09, + 0x19, 0x01, + 0x29, 0x03, + + 0x15, 0x00, + 0x25, 0x01, + 0x95, 0x03, + 0x75, 0x01, + + 0x81, 0x02, + 0x95, 0x01, + 0x75, 0x05, + 0x81, 0x01, + + 0x05, 0x01, + 0x09, 0x30, + 0x09, 0x31, + 0x09, 0x38, + + 0x15, 0x81, + 0x25, 0x7F, + 0x75, 0x08, + 0x95, 0x03, + + 0x81, 0x06, + 0xC0, 0x09, + 0x3c, 0x05, + 0xff, 0x09, + + 0x01, 0x15, + 0x00, 0x25, + 0x01, 0x75, + 0x01, 0x95, + + 0x02, 0xb1, + 0x22, 0x75, + 0x06, 0x95, + 0x01, 0xb1, + + 0x01, 0xc0}; + +/** + * @} + */ + +/** @defgroup USBD_HID_Private_Functions + * @{ + */ + +/** + * @brief USBD_HID_Init + * Initialize the HID interface + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(cfgidx); + + USBD_HID_HandleTypeDef *hhid; + + hhid = &USBD_HID_Instance; + + if (hhid == NULL) + { + pdev->pClassData_HID_Mouse = NULL; + return (uint8_t)USBD_EMEM; + } + + pdev->pClassData_HID_Mouse = (void *)hhid; + + if (pdev->dev_speed == USBD_SPEED_HIGH) + { + pdev->ep_in[HID_MOUSE_IN_EP & 0xFU].bInterval = HID_HS_BINTERVAL; + } + else /* LOW and FULL-speed endpoints */ + { + pdev->ep_in[HID_MOUSE_IN_EP & 0xFU].bInterval = HID_FS_BINTERVAL; + } + + /* Open EP IN */ + (void)USBD_LL_OpenEP(pdev, HID_MOUSE_IN_EP, USBD_EP_TYPE_INTR, HID_EPIN_SIZE); + pdev->ep_in[HID_MOUSE_IN_EP & 0xFU].is_used = 1U; + + hhid->state = HID_IDLE; + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_HID_DeInit + * DeInitialize the HID layer + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(cfgidx); + + /* Close HID EPs */ + (void)USBD_LL_CloseEP(pdev, HID_MOUSE_IN_EP); + pdev->ep_in[HID_MOUSE_IN_EP & 0xFU].is_used = 0U; + pdev->ep_in[HID_MOUSE_IN_EP & 0xFU].bInterval = 0U; + + /* Free allocated memory */ + if (pdev->pClassData_HID_Mouse != NULL) + { +#if (0) + (void)USBD_free(pdev->pClassData_HID_Mouse); +#endif + pdev->pClassData_HID_Mouse = NULL; + } + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_HID_Setup + * Handle the HID specific requests + * @param pdev: instance + * @param req: usb requests + * @retval status + */ +static uint8_t USBD_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef *)pdev->pClassData_HID_Mouse; + USBD_StatusTypeDef ret = USBD_OK; + uint16_t len; + uint8_t *pbuf; + uint16_t status_info = 0U; + + if (hhid == NULL) + { + return (uint8_t)USBD_FAIL; + } + + switch (req->bmRequest & USB_REQ_TYPE_MASK) + { + case USB_REQ_TYPE_CLASS: + switch (req->bRequest) + { + case HID_REQ_SET_PROTOCOL: + hhid->Protocol = (uint8_t)(req->wValue); + break; + + case HID_REQ_GET_PROTOCOL: + (void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->Protocol, 1U); + break; + + case HID_REQ_SET_IDLE: + hhid->IdleState = (uint8_t)(req->wValue >> 8); + break; + + case HID_REQ_GET_IDLE: + (void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->IdleState, 1U); + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + break; + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) + { + case USB_REQ_GET_STATUS: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_GET_DESCRIPTOR: + if ((req->wValue >> 8) == HID_REPORT_DESC) + { + len = MIN(HID_MOUSE_REPORT_DESC_SIZE, req->wLength); + pbuf = HID_MOUSE_ReportDesc; + } + else if ((req->wValue >> 8) == HID_DESCRIPTOR_TYPE) + { + pbuf = USBD_HID_Desc; + len = MIN(USB_HID_DESC_SIZ, req->wLength); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + (void)USBD_CtlSendData(pdev, pbuf, len); + break; + + case USB_REQ_GET_INTERFACE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, (uint8_t *)&hhid->AltSetting, 1U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_SET_INTERFACE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + hhid->AltSetting = (uint8_t)(req->wValue); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_CLEAR_FEATURE: + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + + return (uint8_t)ret; +} + +/** + * @brief USBD_HID_GetCfgFSDesc + * return FS configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_HID_GetFSCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_HID_CfgFSDesc); + + return USBD_HID_CfgFSDesc; +} + +/** + * @brief USBD_HID_GetCfgHSDesc + * return HS configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_HID_GetHSCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_HID_CfgHSDesc); + + return USBD_HID_CfgHSDesc; +} + +/** + * @brief USBD_HID_GetOtherSpeedCfgDesc + * return other speed configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_HID_GetOtherSpeedCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_HID_CfgFSDesc); + + return USBD_HID_CfgFSDesc; +} + +/** + * @brief USBD_HID_DataIn + * handle data IN Stage + * @param pdev: device instance + * @param epnum: endpoint index + * @retval status + */ +static uint8_t USBD_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + UNUSED(epnum); + /* Ensure that the FIFO is empty before a new transfer, this condition could + be caused by a new transfer before the end of the previous transfer */ + ((USBD_HID_HandleTypeDef *)pdev->pClassData_HID_Mouse)->state = HID_IDLE; + + return (uint8_t)USBD_OK; +} + +/** + * @brief DeviceQualifierDescriptor + * return Device Qualifier descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_HID_GetDeviceQualifierDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_HID_DeviceQualifierDesc); + + return USBD_HID_DeviceQualifierDesc; +} + +/** + * @brief USBD_HID_SendReport + * Send HID Report + * @param pdev: device instance + * @param buff: pointer to report + * @retval status + */ +uint8_t USBD_HID_Mouse_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len) +{ + USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef *)pdev->pClassData_HID_Mouse; + + if (hhid == NULL) + { + return (uint8_t)USBD_FAIL; + } + + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + if (hhid->state == HID_IDLE) + { + hhid->state = HID_BUSY; + (void)USBD_LL_Transmit(pdev, HID_MOUSE_IN_EP, report, len); + } + } + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_HID_GetPollingInterval + * return polling interval from endpoint descriptor + * @param pdev: device instance + * @retval polling interval + */ +uint32_t USBD_HID_Mouse_GetPollingInterval(USBD_HandleTypeDef *pdev) +{ + uint32_t polling_interval; + + /* HIGH-speed endpoints */ + if (pdev->dev_speed == USBD_SPEED_HIGH) + { + /* Sets the data transfer polling interval for high speed transfers. + Values between 1..16 are allowed. Values correspond to interval + of 2 ^ (bInterval-1). This option (8 ms, corresponds to HID_HS_BINTERVAL */ + polling_interval = (((1U << (HID_HS_BINTERVAL - 1U))) / 8U); + } + else /* LOW and FULL-speed endpoints */ + { + /* Sets the data transfer polling interval for low and full + speed transfers */ + polling_interval = HID_FS_BINTERVAL; + } + + return ((uint32_t)(polling_interval)); +} + +void USBD_Update_HID_Mouse_DESC(uint8_t *desc, uint8_t itf_no, uint8_t in_ep, uint8_t str_idx) +{ + desc[11] = itf_no; + desc[17] = str_idx; + desc[29] = in_ep; + + HID_MOUSE_IN_EP = in_ep; + HID_MOUSE_ITF_NBR = itf_no; + HID_MOUSE_STR_DESC_IDX = str_idx; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/PRINTER/Inc/usbd_printer.h b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/PRINTER/Inc/usbd_printer.h new file mode 100644 index 0000000..4542a8b --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/PRINTER/Inc/usbd_printer.h @@ -0,0 +1,161 @@ +/** + ****************************************************************************** + * @file usbd_printer.h + * @author MCD Application Team + * @brief header file for the usbd_printer.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_PRNT_H +#define __USB_PRNT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ioreq.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup usbd_PRNT + * @brief This file is the Header file for usbd_PRNT.c + * @{ + */ + + +/** @defgroup usbd_PRNT_Exported_Defines + * @{ + */ +#define PRNT_STR_DESC "STM32 USB PRINTER" + +#ifndef PRNT_DATA_HS_MAX_PACKET_SIZE +#define PRNT_DATA_HS_MAX_PACKET_SIZE 512U /* Endpoint IN & OUT Packet size */ +#endif /* PRNT_DATA_HS_MAX_PACKET_SIZE */ + +#ifndef PRNT_DATA_FS_MAX_PACKET_SIZE +#define PRNT_DATA_FS_MAX_PACKET_SIZE 64U /* Endpoint IN & OUT Packet size */ +#endif /* PRNT_DATA_FS_MAX_PACKET_SIZE */ + +#define USB_PRNT_CONFIG_DESC_SIZE 32U +#define PRNT_DATA_HS_IN_PACKET_SIZE PRNT_DATA_HS_MAX_PACKET_SIZE +#define PRNT_DATA_HS_OUT_PACKET_SIZE PRNT_DATA_HS_MAX_PACKET_SIZE + +#define PRNT_DATA_FS_IN_PACKET_SIZE PRNT_DATA_FS_MAX_PACKET_SIZE +#define PRNT_DATA_FS_OUT_PACKET_SIZE PRNT_DATA_FS_MAX_PACKET_SIZE + +/*---------------------------------------------------------------------*/ +/* PRNT definitions */ +/*---------------------------------------------------------------------*/ +#define PRNT_STATUS_PAPER_EMPTY 0x10U +#define PRNT_STATUS_SELECTED 0x08U +#define PRNT_STATUS_NO_ERROR 0x00U + +#define USB_PRNT_SUBCLASS 0x01U + +#define USB_PRNT_UNIDIRECTIONAL 0x01U +#define USB_PRNT_BIDIRECTIONAL 0x02U + +/* USB PRNT Request types */ +#define PRNT_GET_DEVICE_ID 0x00U +#define PRNT_GET_PORT_STATUS 0x01U +#define PRNT_SOFT_RESET 0x02U +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +typedef struct _USBD_PRNT_Itf +{ + int8_t (*Init)(void); + int8_t (*DeInit)(void); + int8_t (*Control_req)(uint8_t req, uint8_t *pbuf, uint16_t *length); + int8_t (*Receive)(uint8_t *Buf, uint32_t *Len); + +} USBD_PRNT_ItfTypeDef; + +typedef struct +{ + uint32_t data[PRNT_DATA_HS_MAX_PACKET_SIZE / 4U]; /* Force 32-bit alignment */ + uint8_t CmdOpCode; + uint8_t CmdLength; + uint8_t *RxBuffer; + uint8_t *TxBuffer; + uint32_t RxLength; + uint32_t TxLength; + + __IO uint32_t TxState; + __IO uint32_t RxState; +} USBD_PRNT_HandleTypeDef; + +/** @defgroup USBD_CORE_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_Variables + * @{ + */ + +extern USBD_ClassTypeDef USBD_PRNT; + +extern uint8_t PRNT_IN_EP; +extern uint8_t PRNT_OUT_EP; +extern uint8_t PRNT_ITF_NBR; +extern uint8_t PRINTER_STR_DESC_IDX; + +/** + * @} + */ + +/** @defgroup USB_CORE_Exported_Functions + * @{ + */ +uint8_t USBD_PRNT_RegisterInterface(USBD_HandleTypeDef *pdev, USBD_PRNT_ItfTypeDef *fops); +uint8_t USBD_PRNT_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff); +uint8_t USBD_PRNT_ReceivePacket(USBD_HandleTypeDef *pdev); + +void USBD_Update_PRNT_DESC(uint8_t *desc, uint8_t itf_no, uint8_t in_ep, uint8_t out_ep, uint8_t str_idx); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_PRNT_H */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/PRINTER/Src/usbd_printer.c b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/PRINTER/Src/usbd_printer.c new file mode 100644 index 0000000..f195f66 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/PRINTER/Src/usbd_printer.c @@ -0,0 +1,696 @@ +/** + ****************************************************************************** + * @file usbd_printer.c + * @author MCD Application Team + * @brief This file provides the high layer firmware functions to manage the + * following functionalities of the USB printer Class: + * - Initialization and Configuration of high and low layer + * - Enumeration as printer Device (and enumeration for each implemented memory interface) + * - OUT data transfer + * - Command OUT transfer (class requests management) + * - Error management + * + * @verbatim + * + * =================================================================== + * PRINTER Class Driver Description + * =================================================================== + * This driver manages the "Universal Serial Bus Class Definitions for Communications Devices + * Revision 1.2 November 16, 2007" and the sub-protocol specification of "Universal Serial Bus + * printer Class Subclass Specification for PSTN Devices Revision 1.2 February 9, 2007" + * This driver implements the following aspects of the specification: + * - Device descriptor management + * - Configuration descriptor management + * - Enumeration as printer device with 2 data endpoints (IN and OUT) + * - Control Requests management (PRNT_GET_DEVICE_ID,PRNT_GET_PORT_STATUS,PRNT_SOFT_RESET) + * - protocol USB_PRNT_BIDIRECTIONAL + * + * + * + * These aspects may be enriched or modified for a specific user application. + * + * This driver doesn't implement the following aspects of the specification + * (but it is possible to manage these features with some modifications on this driver): + * - Any class-specific aspect relative to communication classes should be managed by user application. + * - All communication classes other than PSTN are not managed + * + * @endverbatim + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* BSPDependencies +- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" +- "stm32xxxxx_{eval}{discovery}_io.c" +EndBSPDependencies */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_printer.h" +#include "usbd_ctlreq.h" + +#define _PRNT_IN_EP 0x81U /* Default: EP1 for data IN */ +#define _PRNT_OUT_EP 0x01U /* Default: EP1 for data OUT */ +#define _PRNT_ITF_NBR 0x00 +#define _PRINTER_STR_DESC_IDX 0x01 + +uint8_t PRNT_IN_EP = _PRNT_IN_EP; +uint8_t PRNT_OUT_EP = _PRNT_OUT_EP; +uint8_t PRNT_ITF_NBR = _PRNT_ITF_NBR; +uint8_t PRINTER_STR_DESC_IDX = _PRINTER_STR_DESC_IDX; + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_PRNT + * @brief usbd core module + * @{ + */ + +/** @defgroup USBD_PRNT_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ +static uint32_t usbd_PRNT_altset = 0U; + +/** @defgroup USBD_PRNT_Private_Defines + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_PRNT_Private_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_PRNT_Private_FunctionPrototypes + * @{ + */ +static uint8_t USBD_PRNT_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_PRNT_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_PRNT_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static uint8_t USBD_PRNT_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum); +static uint8_t USBD_PRNT_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum); + +static uint8_t *USBD_PRNT_GetFSCfgDesc(uint16_t *length); +static uint8_t *USBD_PRNT_GetHSCfgDesc(uint16_t *length); +static uint8_t *USBD_PRNT_GetOtherSpeedCfgDesc(uint16_t *length); +static uint8_t *USBD_PRNT_GetOtherSpeedCfgDesc(uint16_t *length); +uint8_t *USBD_PRNT_GetDeviceQualifierDescriptor(uint16_t *length); + +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_PRNT_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_PRNT_Private_Variables + * @{ + */ + +static USBD_PRNT_HandleTypeDef USBD_PRNT_Instance; + +/* PRNT interface class callbacks structure */ +USBD_ClassTypeDef USBD_PRNT = + { + USBD_PRNT_Init, + USBD_PRNT_DeInit, + USBD_PRNT_Setup, + NULL, + NULL, + USBD_PRNT_DataIn, + USBD_PRNT_DataOut, + NULL, + NULL, + NULL, + USBD_PRNT_GetHSCfgDesc, + USBD_PRNT_GetFSCfgDesc, + USBD_PRNT_GetOtherSpeedCfgDesc, + USBD_PRNT_GetDeviceQualifierDescriptor, +}; + +/* USB PRNT device Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_PRNT_CfgHSDesc[USB_PRNT_CONFIG_DESC_SIZE] __ALIGN_END = + { + /*Configuration Descriptor*/ + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_PRNT_CONFIG_DESC_SIZE, /* wTotalLength:no of returned bytes */ + 0x00, + 0x01, /* bNumInterfaces: 1 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ +#if (USBD_SELF_POWERED == 1U) + 0xC0, /* bmAttributes: Self Powered according to user configuration */ +#else + 0x80, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* MaxPower in mA */ + + /* Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + _PRNT_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: 2 endpoints used */ + 0x07, /* bInterfaceClass: Communication Interface Class */ + 0x01, /* bInterfaceSubClass: Abstract Control Model */ + USB_PRNT_BIDIRECTIONAL, /* bDeviceProtocol */ + _PRINTER_STR_DESC_IDX, /* iInterface */ + + /* Endpoint IN Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _PRNT_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(PRNT_DATA_HS_IN_PACKET_SIZE), /* wMaxPacketSize */ + HIBYTE(PRNT_DATA_HS_IN_PACKET_SIZE), + 0x00, /* bInterval */ + + /* Endpoint OUT Descriptor */ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _PRNT_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(PRNT_DATA_HS_OUT_PACKET_SIZE), /* wMaxPacketSize */ + HIBYTE(PRNT_DATA_HS_OUT_PACKET_SIZE), + 0x00 /* bInterval */ +}; + +/* USB PRNT device Configuration Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_PRNT_CfgFSDesc[USB_PRNT_CONFIG_DESC_SIZE] __ALIGN_END = + { + /*Configuration Descriptor*/ + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_PRNT_CONFIG_DESC_SIZE, /* wTotalLength:no of returned bytes */ + 0x00, + 0x01, /* bNumInterfaces: 1 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ +#if (USBD_SELF_POWERED == 1U) + 0xC0, /* bmAttributes: Self Powered according to user configuration */ +#else + 0x80, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* MaxPower in mA */ + + /*Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + _PRNT_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: 2 endpoints used */ + 0x07, /* bInterfaceClass: Communication Interface Class */ + 0x01, /* bInterfaceSubClass: Abstract Control Model */ + USB_PRNT_BIDIRECTIONAL, /* bDeviceProtocol */ + _PRINTER_STR_DESC_IDX, /* iInterface */ + + /*Endpoint IN Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _PRNT_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(PRNT_DATA_FS_IN_PACKET_SIZE), /* wMaxPacketSize */ + HIBYTE(PRNT_DATA_FS_IN_PACKET_SIZE), + 0x00, /* bInterval */ + + /*Endpoint OUT Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _PRNT_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(PRNT_DATA_FS_OUT_PACKET_SIZE), /* wMaxPacketSize */ + HIBYTE(PRNT_DATA_FS_OUT_PACKET_SIZE), + 0x00 /* bInterval */ +}; + +__ALIGN_BEGIN static uint8_t USBD_PRNT_OtherSpeedCfgDesc[USB_PRNT_CONFIG_DESC_SIZE] __ALIGN_END = + { + /*Configuration Descriptor*/ + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_PRNT_CONFIG_DESC_SIZE, /* wTotalLength:no of returned bytes */ + 0x00, + 0x01, /* bNumInterfaces: 1 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ +#if (USBD_SELF_POWERED == 1U) + 0xC0, /* bmAttributes: Self Powered according to user configuration */ +#else + 0x80, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* MaxPower in mA */ + + /*Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + _PRNT_ITF_NBR, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: 2 endpoints used */ + 0x07, /* bInterfaceClass: Communication Interface Class */ + 0x01, /* bInterfaceSubClass: Abstract Control Model */ + USB_PRNT_BIDIRECTIONAL, /* bDeviceProtocol */ + _PRINTER_STR_DESC_IDX, /* iInterface */ + + /*Endpoint IN Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _PRNT_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(PRNT_DATA_FS_IN_PACKET_SIZE), /* wMaxPacketSize */ + HIBYTE(PRNT_DATA_FS_IN_PACKET_SIZE), + 0x00, /* bInterval */ + + /*Endpoint OUT Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + _PRNT_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(PRNT_DATA_FS_OUT_PACKET_SIZE), /* wMaxPacketSize */ + HIBYTE(PRNT_DATA_FS_OUT_PACKET_SIZE), + 0x00 /* bInterval */ +}; + +/** + * @} + */ + +/** @defgroup USBD_PRNT_Private_Functions + * @{ + */ + +/** + * @brief USBD_PRNT_Init + * Initialize the PRNT interface + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_PRNT_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(cfgidx); + + USBD_PRNT_HandleTypeDef *hPRNT; + uint16_t mps; + hPRNT = &USBD_PRNT_Instance; + + if (hPRNT == NULL) + { + pdev->pClassData_PRNTR = NULL; + return (uint8_t)USBD_EMEM; + } + + /* Setup the pClassData pointer */ + pdev->pClassData_PRNTR = (void *)hPRNT; + + /* Setup the max packet size according to selected speed */ + if (pdev->dev_speed == USBD_SPEED_HIGH) + { + mps = PRNT_DATA_HS_IN_PACKET_SIZE; + } + else + { + mps = PRNT_DATA_FS_IN_PACKET_SIZE; + } + + /* Open EP IN */ + (void)USBD_LL_OpenEP(pdev, PRNT_IN_EP, USBD_EP_TYPE_BULK, mps); + + /* Set endpoint as used */ + pdev->ep_in[PRNT_IN_EP & 0xFU].is_used = 1U; + + /* Open EP OUT */ + (void)USBD_LL_OpenEP(pdev, PRNT_OUT_EP, USBD_EP_TYPE_BULK, mps); + + /* Set endpoint as used */ + pdev->ep_out[PRNT_OUT_EP & 0xFU].is_used = 1U; + + /* Init physical Interface components */ + ((USBD_PRNT_ItfTypeDef *)pdev->pUserData_PRNTR)->Init(); + + /* Prepare Out endpoint to receive next packet */ + (void)USBD_LL_PrepareReceive(pdev, PRNT_OUT_EP, hPRNT->RxBuffer, mps); + + /* End of initialization phase */ + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_PRNT_DeInit + * DeInitialize the PRNT layer + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_PRNT_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(cfgidx); + + /* Close EP IN */ + (void)USBD_LL_CloseEP(pdev, PRNT_IN_EP); + pdev->ep_in[PRNT_IN_EP & 0xFU].is_used = 0U; + + /* Close EP OUT */ + (void)USBD_LL_CloseEP(pdev, PRNT_OUT_EP); + pdev->ep_out[PRNT_OUT_EP & 0xFU].is_used = 0U; + + /* DeInit physical Interface components */ + if (pdev->pClassData_PRNTR != NULL) + { + ((USBD_PRNT_ItfTypeDef *)pdev->pUserData_PRNTR)->DeInit(); +#if (0) + (void)USBD_free(pdev->pClassData_PRNTR); +#endif + pdev->pClassData_PRNTR = NULL; + } + + return 0U; +} + +/** + * @brief USBD_PRNT_Setup + * Handle the PRNT specific requests + * @param pdev: instance + * @param req: usb requests + * @retval status + */ +static uint8_t USBD_PRNT_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_PRNT_HandleTypeDef *hPRNT = (USBD_PRNT_HandleTypeDef *)pdev->pClassData_PRNTR; + USBD_PRNT_ItfTypeDef *hPRNTitf = (USBD_PRNT_ItfTypeDef *)pdev->pUserData_PRNTR; + + USBD_StatusTypeDef ret = USBD_OK; + uint16_t status_info = 0U; + uint16_t data_length; + + switch (req->bmRequest & USB_REQ_TYPE_MASK) + { + case USB_REQ_TYPE_CLASS: + if (req->wLength != 0U) + { + data_length = MIN(req->wLength, PRNT_DATA_HS_MAX_PACKET_SIZE); + + if ((req->bmRequest & 0x80U) != 0U) + { + /* Call the User class interface function to process the command */ + hPRNTitf->Control_req(req->bRequest, (uint8_t *)hPRNT->data, &data_length); + + /* Return the answer to host */ + (void)USBD_CtlSendData(pdev, (uint8_t *)hPRNT->data, data_length); + } + else + { + /* Prepare for control data reception */ + (void)USBD_CtlPrepareRx(pdev, (uint8_t *)hPRNT->data, data_length); + } + } + else + { + data_length = 0U; + hPRNTitf->Control_req(req->bRequest, (uint8_t *)req, &data_length); + } + break; + + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) + { + case USB_REQ_GET_STATUS: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_GET_INTERFACE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, (uint8_t *)&usbd_PRNT_altset, 1U); + } + else + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_SET_INTERFACE: + if (pdev->dev_state != USBD_STATE_CONFIGURED) + { + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + } + break; + + case USB_REQ_CLEAR_FEATURE: + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + break; + + default: + USBD_CtlError(pdev, req); + ret = USBD_FAIL; + break; + } + + return (uint8_t)ret; +} + +/** + * @brief USBD_PRNT_DataIn + * Data sent on non-control IN endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +static uint8_t USBD_PRNT_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + USBD_PRNT_HandleTypeDef *hPRNT = (USBD_PRNT_HandleTypeDef *)pdev->pClassData_PRNTR; + PCD_HandleTypeDef *hpcd = pdev->pData; + + if (hPRNT == NULL) + { + return (uint8_t)USBD_FAIL; + } + + if ((pdev->ep_in[epnum].total_length > 0U) && + ((pdev->ep_in[epnum].total_length % hpcd->IN_ep[epnum].maxpacket) == 0U)) + { + /* Update the packet total length */ + pdev->ep_in[epnum].total_length = 0U; + + /* Send ZLP */ + (void)USBD_LL_Transmit(pdev, epnum, NULL, 0U); + } + else + { + hPRNT->TxState = 0U; + } + + return (uint8_t)USBD_OK; +} +/** + * @brief USBD_PRNT_DataOut + * Data received on non-control Out endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +static uint8_t USBD_PRNT_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + USBD_PRNT_HandleTypeDef *hPRNT = (USBD_PRNT_HandleTypeDef *)pdev->pClassData_PRNTR; + + if (hPRNT == NULL) + { + return (uint8_t)USBD_FAIL; + } + + /* Get the received data length */ + hPRNT->RxLength = USBD_LL_GetRxDataSize(pdev, epnum); + + /* USB data will be immediately processed, this allow next USB traffic being + NAKed till the end of the application Xfer */ + ((USBD_PRNT_ItfTypeDef *)pdev->pUserData_PRNTR)->Receive(hPRNT->RxBuffer, &hPRNT->RxLength); + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_PRNT_GetFSCfgDesc + * Return configuration descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_PRNT_GetFSCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_PRNT_CfgFSDesc); + return USBD_PRNT_CfgFSDesc; +} + +/** + * @brief USBD_PRNT_GetHSCfgDesc + * Return configuration descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_PRNT_GetHSCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_PRNT_CfgHSDesc); + return USBD_PRNT_CfgHSDesc; +} + +/** + * @brief USBD_PRNT_GetOtherSpeedCfgDesc + * Return configuration descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_PRNT_GetOtherSpeedCfgDesc(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_PRNT_OtherSpeedCfgDesc); + return USBD_PRNT_OtherSpeedCfgDesc; +} + +/** + * @brief USBD_PRNT_GetDeviceQualifierDescriptor + * return Device Qualifier descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +uint8_t *USBD_PRNT_GetDeviceQualifierDescriptor(uint16_t *length) +{ + *length = (uint16_t)sizeof(USBD_PRNT_DeviceQualifierDesc); + return USBD_PRNT_DeviceQualifierDesc; +} + +/** + * @brief USBD_PRNT_RegisterInterface + * @param pdev: device instance + * @param fops: Interface callbacks + * @retval status + */ +uint8_t USBD_PRNT_RegisterInterface(USBD_HandleTypeDef *pdev, USBD_PRNT_ItfTypeDef *fops) +{ + /* Check if the fops pointer is valid */ + if (fops == NULL) + { + return (uint8_t)USBD_FAIL; + } + + /* Setup the fops pointer */ + pdev->pUserData_PRNTR = fops; + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_PRNT_SetRxBuffer + * @param pdev: device instance + * @param pbuff: Rx Buffer + * @retval status + */ +uint8_t USBD_PRNT_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff) +{ + USBD_PRNT_HandleTypeDef *hPRNT = (USBD_PRNT_HandleTypeDef *)pdev->pClassData_PRNTR; + + hPRNT->RxBuffer = pbuff; + + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_PRNT_ReceivePacket + * prepare OUT Endpoint for reception + * @param pdev: device instance + * @retval status + */ +uint8_t USBD_PRNT_ReceivePacket(USBD_HandleTypeDef *pdev) +{ + USBD_PRNT_HandleTypeDef *hPRNT = (USBD_PRNT_HandleTypeDef *)pdev->pClassData_PRNTR; + + if (hPRNT == NULL) + { + return (uint8_t)USBD_FAIL; + } + + if (pdev->dev_speed == USBD_SPEED_HIGH) + { + /* Prepare Out endpoint to receive next packet */ + (void)USBD_LL_PrepareReceive(pdev, PRNT_OUT_EP, hPRNT->RxBuffer, + PRNT_DATA_HS_OUT_PACKET_SIZE); + } + else + { + /* Prepare Out endpoint to receive next packet */ + (void)USBD_LL_PrepareReceive(pdev, PRNT_OUT_EP, hPRNT->RxBuffer, + PRNT_DATA_FS_OUT_PACKET_SIZE); + } + + return (uint8_t)USBD_OK; +} + +void USBD_Update_PRNT_DESC(uint8_t *desc, uint8_t itf_no, uint8_t in_ep, uint8_t out_ep, uint8_t str_idx) +{ + desc[11] = itf_no; + desc[17] = str_idx; + desc[20] = in_ep; + desc[27] = out_ep; + + PRNT_IN_EP = in_ep; + PRNT_OUT_EP = out_ep; + PRNT_ITF_NBR = itf_no; + PRINTER_STR_DESC_IDX = str_idx; +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/VIDEO/Inc/usbd_video.h b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/VIDEO/Inc/usbd_video.h new file mode 100644 index 0000000..0469816 --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/VIDEO/Inc/usbd_video.h @@ -0,0 +1,462 @@ +/** + ****************************************************************************** + * @file usbd_video.h + * @author MCD Application Team + * @brief header file for the usbd_video.c file. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_VIDEO_H +#define __USBD_VIDEO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ioreq.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_VIDEO + * @brief This file is the Header file for usbd_video.c + * @{ + */ + + +/** @defgroup usbd_VIDEO_Exported_Defines + * @{ + */ +#define UVC_STR_DESC "STM32 UVC" + +/* USB Video device class specification version 1.10 */ +#ifdef UVC_1_0 +#define UVC_VERSION 0x0100U /* UVC 1.0 */ +#else +#define UVC_VERSION 0x0110U /* UVC 1.1 */ +#endif + +//#define USBD_UVC_FORMAT_UNCOMPRESSED + +/* These defines shall be updated in the usbd_conf.h file */ +#ifndef UVC_WIDTH +#define UVC_WIDTH 400U +#endif /* UVC_WIDTH */ + +#ifndef UVC_HEIGHT +#define UVC_HEIGHT 240U +#endif /* UVC_HEIGHT */ + +#ifndef UVC_CAM_FPS_FS +#define UVC_CAM_FPS_FS 10U +#endif /* UVC_CAM_FPS_FS */ + +#ifndef UVC_CAM_FPS_HS +#define UVC_CAM_FPS_HS 5U +#endif /* UVC_CAM_FPS_HS */ + +#ifndef UVC_PACKET_SIZE +#define UVC_PACKET_SIZE 512U +#endif /* UVC_PACKET_SIZE */ + +#ifndef UVC_MAX_FRAME_SIZE +#define UVC_MAX_FRAME_SIZE (UVC_WIDTH * UVC_HEIGHT * 16U / 2U) +#endif /* UVC_MAX_FRAME_SIZE */ + +#ifndef UVC_COLOR_PRIMARIE +#define UVC_COLOR_PRIMARIE 0x01U +#endif /* UVC_COLOR_PRIMARIE */ + +#ifndef UVC_TFR_CHARACTERISTICS +#define UVC_TFR_CHARACTERISTICS 0x01U +#endif /* UVC_TFR_CHARACTERISTICS */ + +#ifndef UVC_MATRIX_COEFFICIENTS +#define UVC_MATRIX_COEFFICIENTS 0x04U +#endif /* UVC_MATRIX_COEFFICIENTS */ + +#ifndef UVC_BITS_PER_PIXEL +#define UVC_BITS_PER_PIXEL 12U +#endif /* UVC_BITS_PER_PIXEL */ + +#define UVC_GUID_YUY2 0x32595559U +#define UVC_GUID_NV12 0x3231564EU + +#ifndef UVC_UNCOMPRESSED_GUID +#define UVC_UNCOMPRESSED_GUID UVC_GUID_NV12 +#endif /* UVC_UNCOMPRESSED_GUID */ + +#define UVC_INTERVAL(n) (10000000U/(n)) + +#define UVC_MIN_BIT_RATE(n) (UVC_WIDTH * UVC_HEIGHT * 16U * (n)) /* 16 bit */ +#define UVC_MAX_BIT_RATE(n) (UVC_WIDTH * UVC_HEIGHT * 16U * (n)) /* 16 bit */ + +#define UVC_PACKETS_IN_FRAME(n) (UVC_MAX_FRAME_SIZE / (n)) + +#ifndef UVC_ISO_FS_MPS +#define UVC_ISO_FS_MPS 256U +#endif + +#ifndef UVC_ISO_HS_MPS +#define UVC_ISO_HS_MPS 512U +#endif + +#ifndef UVC_HEADER_PACKET_CNT +#define UVC_HEADER_PACKET_CNT 0x01U +#endif + + +#define UVC_REQ_READ_MASK 0x80U +#define UVC_TOTAL_IF_NUM 0x02U + +#ifdef USBD_UVC_FORMAT_UNCOMPRESSED +#define UVC_CONFIG_DESC_SIZE (0x88U + 0x16U) +#else +#define UVC_CONFIG_DESC_SIZE 0x88U +#endif + +#define UVC_TOTAL_BUF_SIZE 0x04U + +#define UVC_VC_EP_DESC_SIZE 0x05U +#define UVC_STREAMING_EP_DESC_SIZE 0x07U +#define UVC_EP_DESC_TYPE 0x25U + +/* Video Interface Class Codes*/ +#define UVC_CC_VIDEO 0x0EU + +#define UVC_PLAY_STATUS_STOP 0x00U +#define UVC_PLAY_STATUS_READY 0x01U +#define UVC_PLAY_STATUS_STREAMING 0x02U + +#ifndef WBVAL +#define WBVAL(x) ((x) & 0xFFU),(((x) >> 8) & 0xFFU) +#endif +#ifndef DBVAL +#define DBVAL(x) ((x)& 0xFFU),(((x) >> 8) & 0xFFU),(((x)>> 16) & 0xFFU),(((x) >> 24) & 0xFFU) +#endif + +/* Video Interface Protocol Codes */ +#define PC_PROTOCOL_UNDEFINED 0x00U + +#define VIDEO_VC_IF_HEADER_DESC_SIZE 0x0DU +#define VIDEO_IN_TERMINAL_DESC_SIZE 0x08U +#define VIDEO_OUT_TERMINAL_DESC_SIZE 0x09U +#define VIDEO_VS_IF_IN_HEADER_DESC_SIZE 0x0EU + +#define VS_FORMAT_UNCOMPRESSED_DESC_SIZE 0x1BU +#define VS_FORMAT_MJPEG_DESC_SIZE 0x0BU +#define VS_FRAME_DESC_SIZE 0x1EU +#define VS_COLOR_MATCHING_DESC_SIZE 0x06U + +#ifdef USBD_UVC_FORMAT_UNCOMPRESSED +#define VS_FORMAT_DESC_SIZE VS_FORMAT_UNCOMPRESSED_DESC_SIZE +#define VS_FORMAT_SUBTYPE VS_FORMAT_UNCOMPRESSED +#define VS_FRAME_SUBTYPE VS_FRAME_UNCOMPRESSED + +#define VC_HEADER_SIZE (VIDEO_VS_IF_IN_HEADER_DESC_SIZE + \ + VS_FORMAT_UNCOMPRESSED_DESC_SIZE + \ + VS_FRAME_DESC_SIZE + \ + VS_COLOR_MATCHING_DESC_SIZE) +#else +#define VS_FORMAT_DESC_SIZE VS_FORMAT_MJPEG_DESC_SIZE +#define VS_FORMAT_SUBTYPE VS_FORMAT_MJPEG +#define VS_FRAME_SUBTYPE VS_FRAME_MJPEG + +#define VC_HEADER_SIZE (VIDEO_VS_IF_IN_HEADER_DESC_SIZE + \ + VS_FORMAT_DESC_SIZE + \ + VS_FRAME_DESC_SIZE) +#endif + +/* + * Video Class specification release 1.1 + * Appendix A. Video Device Class Codes defines + */ + +/* Video Interface Subclass values */ +#define SC_UNDEFINED 0x00U +#define SC_VIDEOCONTROL 0x01U +#define SC_VIDEOSTREAMING 0x02U +#define SC_VIDEO_INTERFACE_COLLECTION 0x03U + +/* Video Class-Specific Descriptor Types */ +#define CS_UNDEFINED 0x20U +#define CS_DEVICE 0x21U +#define CS_CONFIGURATION 0x22U +#define CS_STRING 0x23U +#define CS_INTERFACE 0x24U +#define CS_ENDPOINT 0x25U + +/* Video Class-Specific VideoControl Interface Descriptor Subtypes */ +#define VC_DESCRIPTOR_UNDEFINED 0x00U +#define VC_HEADER 0x01U +#define VC_INPUT_TERMINAL 0x02U +#define VC_OUTPUT_TERMINAL 0x03U +#define VC_SELECTOR_UNIT 0x04U +#define VC_PROCESSING_UNIT 0x05U +#define VC_EXTENSION_UNIT 0x06U + +/* Video Class-Specific VideoStreaming Interface Descriptor Subtypes */ +#define VS_UNDEFINED 0x00U +#define VS_INPUT_HEADER 0x01U +#define VS_OUTPUT_HEADER 0x02U +#define VS_STILL_IMAGE_FRAME 0x03U +#define VS_FORMAT_UNCOMPRESSED 0x04U +#define VS_FRAME_UNCOMPRESSED 0x05U +#define VS_FORMAT_MJPEG 0x06U +#define VS_FRAME_MJPEG 0x07U +#define VS_FORMAT_MPEG2TS 0x0AU +#define VS_FORMAT_DV 0x0CU +#define VS_COLORFORMAT 0x0DU +#define VS_FORMAT_FRAME_BASED 0x10U +#define VS_FRAME_FRAME_BASED 0x11U +#define VS_FORMAT_STREAM_BASED 0x12U + +/* Video Class-Specific Request values */ +#define UVC_RQ_UNDEFINED 0x00U +#define UVC_SET_CUR 0x01U +#define UVC_GET_CUR 0x81U +#define UVC_GET_MIN 0x82U +#define UVC_GET_MAX 0x83U +#define UVC_GET_RES 0x84U +#define UVC_GET_LEN 0x85U +#define UVC_GET_INFO 0x86U +#define UVC_GET_DEF 0x87U + +/* VideoControl Interface Control Selectors */ +#define VC_CONTROL_UNDEFINED 0x00U +#define VC_VIDEO_POWER_MODE_CONTROL 0x01U +#define VC_REQUEST_ERROR_CODE_CONTROL 0x02U + +/* Request Error Code Control */ +#define UVC_NO_ERROR_ERR 0x00U +#define UVC_NOT_READY_ERR 0x01U +#define UVC_WRONG_STATE_ERR 0x02U +#define UVC_POWER_ERR 0x03U +#define UVC_OUT_OF_RANGE_ERR 0x04U +#define UVC_INVALID_UNIT_ERR 0x05U +#define UVC_INVALID_CONTROL_ERR 0x06U +#define UVC_INVALID_REQUEST_ERR 0x07U +#define UVC_UNKNOWN_ERR 0xFFU + +/*Terminal Control Selectors*/ +#define TE_CONTROL_UNDEFINED 0x00U + +/* Selector Unit Control Selectors */ +#define SU_CONTROL_UNDEFINED 0x00U +#define SU_INPUT_SELECT_CONTROL 0x01U + +/* Camera Terminal Control Selectors */ +#define CT_CONTROL_UNDEFINED 0x00U +#define CT_SCANNING_MODE_CONTROL 0x01U +#define CT_AE_MODE_CONTROL 0x02U +#define CT_AE_PRIORITY_CONTROL 0x03U +#define CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04U +#define CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05U +#define CT_FOCUS_ABSOLUTE_CONTROL 0x06U +#define CT_FOCUS_RELATIVE_CONTROL 0x07U +#define CT_FOCUS_AUTO_CONTROL 0x08U +#define CT_IRIS_ABSOLUTE_CONTROL 0x09U +#define CT_IRIS_RELATIVE_CONTROL 0x0AU +#define CT_ZOOM_ABSOLUTE_CONTROL 0x0BU +#define CT_ZOOM_RELATIVE_CONTROL 0x0CU +#define CT_PANTILT_ABSOLUTE_CONTROL 0x0DU +#define CT_PANTILT_RELATIVE_CONTROL 0x0EU +#define CT_ROLL_ABSOLUTE_CONTROL 0x0FU +#define CT_ROLL_RELATIVE_CONTROL 0x10U +#define CT_PRIVACY_CONTROL 0x11U + +/* Processing Unit Control Selectors */ +#define PU_CONTROL_UNDEFINED 0x00U +#define PU_BACKLIGHT_COMPENSATION_CONTROL 0x01U +#define PU_BRIGHTNESS_CONTROL 0x02U +#define PU_CONTRAST_CONTROL 0x03U +#define PU_GAIN_CONTROL 0x04U +#define PU_POWER_LINE_FREQUENCY_CONTROL 0x05U +#define PU_HUE_CONTROL 0x06U +#define PU_SATURATION_CONTROL 0x07U +#define PU_SHARPNESS_CONTROL 0x08U +#define PU_GAMMA_CONTROL 0x09U +#define PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0AU +#define PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0BU +#define PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0CU +#define PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0DU +#define PU_DIGITAL_MULTIPLIER_CONTROL 0x0EU +#define PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0FU +#define PU_HUE_AUTO_CONTROL 0x10U +#define PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11U +#define PU_ANALOG_LOCK_STATUS_CONTROL 0x12U + +/*Extension Unit Control Selectors */ +#define XU_CONTROL_UNDEFINED 0x00U + +/* VideoStreaming Interface Control Selectors */ +#define VS_CONTROL_UNDEFINED 0x00U +#define VS_PROBE_CONTROL 0x100U +#define VS_COMMIT_CONTROL 0x200U +#define VS_STILL_PROBE_CONTROL 0x03U +#define VS_STILL_COMMIT_CONTROL 0x04U +#define VS_STILL_IMAGE_TRIGGER_CONTROL 0x05U +#define VS_STREAM_ERROR_CODE_CONTROL 0x06U +#define VS_GENERATE_KEY_FRAME_CONTROL 0x07U +#define VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08U +#define VS_SYNC_DELAY_CONTROL 0x09U + + +/* Control Capabilities */ +#define UVC_SUPPORTS_GET 0x01U +#define UVC_SUPPORTS_SET 0x02U +#define UVC_STATE_DISABLED 0x04U +#define UVC_AUTOUPDATE_CONTROL 0x08U +#define UVC_ASYNCHRONOUS_CONTROL 0x10U + +/* USB Terminal Types */ +#define TT_VENDOR_SPECIFIC 0x0100U +#define TT_STREAMING 0x0101U + +/* Input Terminal Types */ +#define ITT_VENDOR_SPECIFIC 0x0200U +#define ITT_CAMERA 0x0201U +#define ITT_MEDIA_TRANSPORT_INPUT 0x0202U + +/*Output Terminal Types */ +#define OTT_VENDOR_SPECIFIC 0x0300U +#define OTT_DISPLAY 0x0301U +#define OTT_MEDIA_TRANSPORT_OUTPUT 0x0302U + +/* External Terminal Types */ +#define EXTERNAL_VENDOR_SPECIFIC 0x0400U +#define COMPOSITE_CONNECTOR 0x0401U +#define SVIDEO_CONNECTOR 0x0402U +#define COMPONENT_CONNECTOR 0x0403U + + /* VIDEO Commands enumeration */ + typedef enum + { + VIDEO_CMD_START = 1U, + VIDEO_CMD_PLAY, + VIDEO_CMD_STOP, + } VIDEO_CMD_TypeDef; + + typedef enum + { + VIDEO_OFFSET_NONE = 0U, + VIDEO_OFFSET_HALF, + VIDEO_OFFSET_FULL, + VIDEO_OFFSET_UNKNOWN, + } VIDEO_OffsetTypeDef; + + typedef struct _VIDEO_DescHeader + { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + } USBD_VIDEO_DescHeader_t; + + typedef struct + { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bFrameIndex; + uint8_t bmCapabilities; + uint16_t wWidth; + uint16_t wHeight; + uint32_t dwMinBitRate; + uint32_t dwMaxBitRate; + uint32_t dwMaxVideoFrameBufSize; + uint32_t dwDefaultFrameInterval; + uint8_t bFrameIntervalType; + uint32_t dwMinFrameInterval; + uint32_t dwMaxFrameInterval; + uint32_t dwFrameIntervalStep; + } __PACKED USBD_VIDEO_VSFrameDescTypeDef; + + typedef struct + { + uint8_t cmd; + uint8_t data[USB_MAX_EP0_SIZE]; + uint8_t len; + uint8_t unit; + } USBD_VIDEO_ControlTypeDef; + + typedef struct + { + uint32_t interface; + uint32_t uvc_state; + uint8_t buffer[UVC_TOTAL_BUF_SIZE]; + VIDEO_OffsetTypeDef offset; + USBD_VIDEO_ControlTypeDef control; + } USBD_VIDEO_HandleTypeDef; + + typedef struct + { + int8_t (*Init)(void); + int8_t (*DeInit)(void); + int8_t (*Control)(uint8_t, uint8_t *, uint16_t); + int8_t (*Data)(uint8_t **, uint16_t *, uint16_t *); + uint8_t *pStrDesc; + } USBD_VIDEO_ItfTypeDef; + + /* UVC uses only 26 first bytes */ + typedef struct + { + uint16_t bmHint; + uint8_t bFormatIndex; + uint8_t bFrameIndex; + uint32_t dwFrameInterval; + uint16_t wKeyFrameRate; + uint16_t wPFrameRate; + uint16_t wCompQuality; + uint16_t wCompWindowSize; + uint16_t wDelay; + uint32_t dwMaxVideoFrameSize; + uint32_t dwMaxPayloadTransferSize; + uint32_t dwClockFrequency; + uint8_t bmFramingInfo; + uint8_t bPreferedVersion; + uint8_t bMinVersion; + uint8_t bMaxVersion; + } __PACKED USBD_VideoControlTypeDef; + + extern USBD_ClassTypeDef USBD_VIDEO; + + extern uint8_t UVC_IN_EP; + extern uint8_t UVC_VC_IF_NUM; + extern uint8_t UVC_VS_IF_NUM; + extern uint8_t UVC_STR_DESC_IDX; + + /** + * @} + */ + + /** @defgroup USB_CORE_Exported_Functions + * @{ + */ + + uint8_t USBD_VIDEO_RegisterInterface(USBD_HandleTypeDef *pdev, USBD_VIDEO_ItfTypeDef *fops); + + void USBD_Update_UVC_DESC(uint8_t *desc, uint8_t vc_itf, uint8_t vs_itf, uint8_t in_ep, uint8_t str_idx); + + /** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* _USBD_VIDEO_H_ */ diff --git a/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/VIDEO/Src/usbd_video.c b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/VIDEO/Src/usbd_video.c new file mode 100644 index 0000000..facd5af --- /dev/null +++ b/USBD_Test/Middlewares/Third_Party/AL94_USB_Composite/COMPOSITE/Class/VIDEO/Src/usbd_video.c @@ -0,0 +1,1081 @@ +/** + ****************************************************************************** + * @file usbd_video.c + * @author MCD Application Team + * @brief This file provides the Video core functions. + * + * @verbatim + * + * =================================================================== + * VIDEO Class Description + * =================================================================== + * This driver manages the Video Class 1.1 following the "USB Device Class Definition for + * Video Devices V1.0 Mar 18, 98". + * This driver implements the following aspects of the specification: + * - Device descriptor management + * - Configuration descriptor management + * - Interface Association Descriptor + * -Standard VC Interface Descriptor = interface 0 + * -Standard Vs Interface Descriptor = interface 1 + * - 1 Video Streaming Interface + * - 1 Video Streaming Endpoint + * - 1 Video Terminal Input (camera) + * - Video Class-Specific AC Interfaces + * - Video Class-Specific AS Interfaces + * - VideoControl Requests + * - Video Synchronization type: Asynchronous + * The current Video class version supports the following Video features: + * - image JPEG format + * - Asynchronous Endpoints + * + * @note In HS mode and when the USB DMA is used, all variables and data structures + * dealing with the DMA during the transaction process should be 32-bit aligned. + * + * + * @endverbatim + * + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2020 STMicroelectronics. + * All rights reserved.

+ * + * 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: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_video.h" +#include "usbd_ctlreq.h" +#include "usbd_core.h" + +#define _UVC_IN_EP 0x81U +#define _UVC_VC_IF_NUM 0x00U +#define _UVC_VS_IF_NUM 0x01U +#define _UVC_STR_DESC_IDX 0x00U + +uint8_t UVC_IN_EP = _UVC_IN_EP; +uint8_t UVC_VC_IF_NUM = _UVC_VC_IF_NUM; +uint8_t UVC_VS_IF_NUM = _UVC_VS_IF_NUM; +uint8_t UVC_STR_DESC_IDX = _UVC_STR_DESC_IDX; + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_VIDEO + * @brief USB Device Video Class core module + * @{ + */ + +/** @defgroup USBD_VIDEO_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_VIDEO_Private_Defines + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_VIDEO_Private_Macros + * @{ + */ + +/* VIDEO Device library callbacks */ +static uint8_t USBD_VIDEO_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_VIDEO_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +static uint8_t USBD_VIDEO_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static uint8_t *USBD_VIDEO_GetFSCfgDesc(uint16_t *length); +static uint8_t *USBD_VIDEO_GetHSCfgDesc(uint16_t *length); +static uint8_t *USBD_VIDEO_GetOtherSpeedCfgDesc(uint16_t *length); +static uint8_t *USBD_VIDEO_GetDeviceQualifierDesc(uint16_t *length); +static uint8_t USBD_VIDEO_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum); +static uint8_t USBD_VIDEO_SOF(USBD_HandleTypeDef *pdev); +static uint8_t USBD_VIDEO_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum); + +/* VIDEO Requests management functions */ +static void VIDEO_REQ_GetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +static void VIDEO_REQ_SetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); + +static USBD_VIDEO_DescHeader_t *USBD_VIDEO_GetNextDesc(uint8_t *pbuf, uint16_t *ptr); +static void *USBD_VIDEO_GetEpDesc(uint8_t *pConfDesc, uint8_t EpAddr); +static void *USBD_VIDEO_GetVSFrameDesc(uint8_t *pConfDesc); + +/** + * @} + */ + +/** @defgroup USBD_VIDEO_Private_Variables + * @{ + */ +static USBD_VIDEO_HandleTypeDef USBD_VIDEO_Instance; + +USBD_ClassTypeDef USBD_VIDEO = + { + USBD_VIDEO_Init, + USBD_VIDEO_DeInit, + USBD_VIDEO_Setup, + NULL, + NULL, + USBD_VIDEO_DataIn, + NULL, + USBD_VIDEO_SOF, + USBD_VIDEO_IsoINIncomplete, + NULL, + USBD_VIDEO_GetHSCfgDesc, + USBD_VIDEO_GetFSCfgDesc, + USBD_VIDEO_GetOtherSpeedCfgDesc, + USBD_VIDEO_GetDeviceQualifierDesc, +}; + +/* USB VIDEO device Configuration Descriptor (same for all speeds thanks to user defines) */ +__ALIGN_BEGIN static uint8_t USBD_VIDEO_CfgDesc[UVC_CONFIG_DESC_SIZE] __ALIGN_END = + { + /* Configuration 1 */ + USB_CONF_DESC_SIZE, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + LOBYTE(UVC_CONFIG_DESC_SIZE), /* wTotalLength: no of returned bytes */ + HIBYTE(UVC_CONFIG_DESC_SIZE), + 0x02, /* bNumInterfaces: 2 interfaces */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ +#if (USBD_SELF_POWERED == 1U) + 0xC0, /* bmAttributes: Bus Powered according to user configuration */ +#else + 0x80, /* bmAttributes: Bus Powered according to user configuration */ +#endif + USBD_MAX_POWER, /* bMaxPower in mA according to user configuration */ + + /* Interface Association Descriptor */ + USB_IAD_DESC_SIZE, /* bLength: Interface Association Descriptor size */ + USB_DESC_TYPE_IAD, /* bDescriptorType: interface association */ + _UVC_VC_IF_NUM, /* bFirstInterface */ + 0x02, /* bInterfaceCount */ + UVC_CC_VIDEO, /* bFunctionClass: Video class */ + SC_VIDEO_INTERFACE_COLLECTION, /* bFunctionSubClass: Video Interface Collection */ + PC_PROTOCOL_UNDEFINED, /* bInterfaceProtocol: protocol undefined */ + _UVC_STR_DESC_IDX, /* iFunction */ + + /* Standard VC (Video Control) Interface Descriptor = interface 0 */ + USB_IF_DESC_SIZE, /* bLength: interface descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: interface */ + _UVC_VC_IF_NUM, /* bInterfaceNumber: interface number */ + 0x00, /* bAlternateSetting: index of this alternate setting */ + 0x00, /* bNumEndpoints: No endpoints used for this interface */ + UVC_CC_VIDEO, /* bInterfaceClass: Video Class */ + SC_VIDEOCONTROL, /* bInterfaceSubClass: Video Control */ + PC_PROTOCOL_UNDEFINED, /* bInterfaceProtocol: protocol is undefined */ + 0x00, /* iFunction: index of string descriptor relative to this item */ + + /* Class-specific VC Interface Descriptor */ + VIDEO_VC_IF_HEADER_DESC_SIZE, /* bLength */ + CS_INTERFACE, /* bDescriptorType */ + VC_HEADER, /* bDescriptorSubtype */ + LOBYTE(UVC_VERSION), + HIBYTE(UVC_VERSION), /* bcdUVC: UVC1.0 or UVC1.1 revision */ + VS_FRAME_DESC_SIZE, /* wTotalLength: total size of class-specific descriptors */ + 0x00, + 0x00, /* dwClockFrequency: not used. 48 Mhz value is set, but not used */ + 0x6C, + 0xDC, + 0x02, + 0x01, /* bInCollection: number of streaming interfaces */ + _UVC_VS_IF_NUM, /* baInterfaceNr(1): VideoStreaming interface 1 is part of VC interface */ + + /* Input Terminal Descriptor */ + VIDEO_IN_TERMINAL_DESC_SIZE, /* bLength: Input terminal descriptor size */ + CS_INTERFACE, /* bDescriptorType: INTERFACE */ + VC_INPUT_TERMINAL, /* bDescriptorSubtype: INPUT_TERMINAL */ + 0x01, /* bTerminalID: ID of this Terminal */ + LOBYTE(ITT_VENDOR_SPECIFIC), /* wTerminalType: 0x0200 ITT_VENDOR_SPECIFIC */ + HIBYTE(ITT_VENDOR_SPECIFIC), + 0x00, /* bAssocTerminal: no Terminal is associated */ + 0x00, /* iTerminal: index of string descriptor relative to this item */ + + /* Output Terminal Descriptor */ + VIDEO_OUT_TERMINAL_DESC_SIZE, /* bLength: output terminal descriptor size */ + CS_INTERFACE, /* bDescriptorType */ + VC_OUTPUT_TERMINAL, /* bDescriptorSubtype */ + 0x02, /* bTerminalID */ + LOBYTE(TT_STREAMING), /* wTerminalType: USB streaming terminal */ + HIBYTE(TT_STREAMING), + 0x00, /* bAssocTerminal: no Terminal is associated */ + 0x01, /* bSourceID: input is connected to output unit ID 1 */ + 0x00, /* iTerminal: index of string descriptor relative to this item */ + + /* Standard VS (Video Streaming) Interface Descriptor = interface 1, alternate setting 0 = Zero Bandwidth + (when no data are sent from the device) */ + USB_IF_DESC_SIZE, /* bLength: interface descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType */ + _UVC_VS_IF_NUM, /* bInterfaceNumber */ + 0x00, /* bAlternateSetting */ + 0x00, /* bNumEndpoints: no endpoints used for alternate setting 0 */ + UVC_CC_VIDEO, /* bInterfaceClass */ + SC_VIDEOSTREAMING, /* bInterfaceSubClass */ + PC_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ + 0x00, /* iInterface: index of string descriptor relative to this item */ + + /* Class-specific VS Header Descriptor (Input) */ + VIDEO_VS_IF_IN_HEADER_DESC_SIZE, /* bLength */ + CS_INTERFACE, /* bDescriptorType */ + VS_INPUT_HEADER, /* bDescriptorSubtype */ + 0x01, /* bNumFormats: 1 format descriptor is used */ + VC_HEADER_SIZE, + 0x00, /* Total size of Video Control Specific Descriptors */ + _UVC_IN_EP, /* bEndPointAddress: In endpoint is used for the alternate setting */ + 0x00, /* bmInfo: dynamic format change not supported */ + 0x02, /* bTerminalLink: output to terminal ID 2 */ + 0x00, /* bStillCaptureMethod: not supported */ + 0x00, /* bTriggerSupport: not supported */ + 0x00, /* bTriggerUsage: not supported */ + 0x01, /* bControlSize: 1 byte field size */ + 0x00, /* bmaControls: No specific controls used */ + + /* Payload Format Descriptor */ + VS_FORMAT_DESC_SIZE, /* blength */ + CS_INTERFACE, /* bDescriptorType */ + VS_FORMAT_SUBTYPE, /* bDescriptorSubType */ + 0x01, /* bFormatIndex */ + 0x01, /* bNumFrameDescriptor */ +#ifdef USBD_UVC_FORMAT_UNCOMPRESSED + DBVAL(UVC_UNCOMPRESSED_GUID), /* Giud Format: YUY2 {32595559-0000-0010-8000-00AA00389B71} */ + 0x00, 0x00, + 0x10, 0x00, + 0x80, 0x00, + 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71, + UVC_BITS_PER_PIXEL, /* bBitsPerPixel : Number of bits per pixel */ +#else + 0x01, /* bmFlags: FixedSizeSamples */ +#endif + 0x01, /* bDefaultFrameIndex: default frame used is frame 1 (only one frame used) */ + 0x00, /* bAspectRatioX: not required by specification */ + 0x00, /* bAspectRatioY: not required by specification */ + 0x00, /* bInterlaceFlags: non interlaced stream */ + 0x00, /* bCopyProtect: no protection restrictions */ + + /* Class-specific VS (Video Streaming) Frame Descriptor */ + VS_FRAME_DESC_SIZE, /* bLength */ + CS_INTERFACE, /* bDescriptorType */ + VS_FRAME_SUBTYPE, /* bDescriptorSubType */ + 0x01, /* bFrameIndex */ +#ifdef USBD_UVC_FORMAT_UNCOMPRESSED + 0x00, /* bmCapabilities: no till image capture */ +#else + 0x02, /* bmCapabilities: fixed frame rate supported */ +#endif + WBVAL(UVC_WIDTH), /* wWidth: Image Frame Width */ + WBVAL(UVC_HEIGHT), /* wHeight: Image Frame Height */ + DBVAL(UVC_MIN_BIT_RATE(UVC_CAM_FPS_FS)), /* dwMinBitRate: Minimum supported bit rate in bits/s */ + DBVAL(UVC_MAX_BIT_RATE(UVC_CAM_FPS_FS)), /* dwMaxBitRate: Maximum supported bit rate in bits/s */ + DBVAL(UVC_MAX_FRAME_SIZE), /* dwMaxVideoFrameBufSize: Maximum video frame size, in bytes */ + DBVAL(UVC_INTERVAL(UVC_CAM_FPS_FS)), /* dwDefaultFrameInterval: following number of FPS */ + 0x01, /* bFrameIntervalType: Discrete frame interval type */ + DBVAL(UVC_INTERVAL(UVC_CAM_FPS_FS)), /* dwMinFrameInterval: One supported value of interval (FPS) */ + +#ifdef USBD_UVC_FORMAT_UNCOMPRESSED + /* Color Matching Descriptor */ + VS_COLOR_MATCHING_DESC_SIZE, /* bLength */ + CS_INTERFACE, /* bDescriptorType: CS_INTERFACE */ + VS_COLORFORMAT, /* bDescriptorSubType: VS_COLORFORMAT */ + UVC_COLOR_PRIMARIE, /* bColorPrimarie: 1: BT.709, sRGB (default) */ + UVC_TFR_CHARACTERISTICS, /* bTransferCharacteristics: 1: BT.709 (default) */ + UVC_MATRIX_COEFFICIENTS, /* bMatrixCoefficients: 4: BT.601, (default) */ +#endif + + /* Standard VS Interface Descriptor = interface 1, alternate setting 1 = data transfer mode */ + USB_IF_DESC_SIZE, /* bLength */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType */ + _UVC_VS_IF_NUM, /* bInterfaceNumber */ + 0x01, /* bAlternateSetting */ + 0x01, /* bNumEndpoints: one endpoint is used */ + UVC_CC_VIDEO, /* bInterfaceClass */ + SC_VIDEOSTREAMING, /* bInterfaceSubClass */ + PC_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ + 0x00, /* iInterface: index of string descriptor relative to this item */ + + /* Standard VS (Video Streaming) data Endpoint */ + USB_EP_DESC_SIZE, /* bLength */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType */ + _UVC_IN_EP, /* bEndpointAddress */ + 0x05, /* bmAttributes: ISO transfer */ + LOBYTE(UVC_ISO_FS_MPS), /* wMaxPacketSize */ + HIBYTE(UVC_ISO_FS_MPS), + 0x01, /* bInterval: 1 frame interval */ +}; + +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_VIDEO_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END = + { + USB_LEN_DEV_QUALIFIER_DESC, + USB_DESC_TYPE_DEVICE_QUALIFIER, + 0x00, + 0x02, + 0xEF, + 0x02, + 0x01, + 0x40, + 0x01, + 0x00, +}; + +/* Video Commit data structure */ +static USBD_VideoControlTypeDef video_Commit_Control = + { + .bmHint = 0x0000U, + .bFormatIndex = 0x01U, + .bFrameIndex = 0x01U, + .dwFrameInterval = UVC_INTERVAL(UVC_CAM_FPS_FS), + .wKeyFrameRate = 0x0000U, + .wPFrameRate = 0x0000U, + .wCompQuality = 0x0000U, + .wCompWindowSize = 0x0000U, + .wDelay = 0x0000U, + .dwMaxVideoFrameSize = 0x0000U, + .dwMaxPayloadTransferSize = 0x00000000U, + .dwClockFrequency = 0x00000000U, + .bmFramingInfo = 0x00U, + .bPreferedVersion = 0x00U, + .bMinVersion = 0x00U, + .bMaxVersion = 0x00U, +}; + +/* Video Probe data structure */ +static USBD_VideoControlTypeDef video_Probe_Control = + { + .bmHint = 0x0000U, + .bFormatIndex = 0x01U, + .bFrameIndex = 0x01U, + .dwFrameInterval = UVC_INTERVAL(UVC_CAM_FPS_FS), + .wKeyFrameRate = 0x0000U, + .wPFrameRate = 0x0000U, + .wCompQuality = 0x0000U, + .wCompWindowSize = 0x0000U, + .wDelay = 0x0000U, + .dwMaxVideoFrameSize = 0x0000U, + .dwMaxPayloadTransferSize = 0x00000000U, + .dwClockFrequency = 0x00000000U, + .bmFramingInfo = 0x00U, + .bPreferedVersion = 0x00U, + .bMinVersion = 0x00U, + .bMaxVersion = 0x00U, +}; + +/** + * @} + */ + +/** @defgroup USBD_VIDEO_Private_Functions + * @{ + */ + +/** + * @brief USBD_VIDEO_Init + * Initialize the VIDEO interface + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_VIDEO_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + USBD_VIDEO_HandleTypeDef *hVIDEO; + + /* Allocate memory for the video control structure */ + hVIDEO = &USBD_VIDEO_Instance; + + /* Check if allocated point is NULL, then exit with error code */ + if (hVIDEO == NULL) + { + return (uint8_t)USBD_FAIL; + } + + /* Assign the pClassData_UVC pointer to the allocated structure */ + pdev->pClassData_UVC = (void *)hVIDEO; + + /* Open EP IN */ + if (pdev->dev_speed == USBD_SPEED_HIGH) + { + (void)USBD_LL_OpenEP(pdev, UVC_IN_EP, USBD_EP_TYPE_ISOC, UVC_ISO_HS_MPS); + + pdev->ep_in[UVC_IN_EP & 0xFU].is_used = 1U; + pdev->ep_in[UVC_IN_EP & 0xFU].maxpacket = UVC_ISO_HS_MPS; + } + else + { + (void)USBD_LL_OpenEP(pdev, UVC_IN_EP, USBD_EP_TYPE_ISOC, UVC_ISO_FS_MPS); + + pdev->ep_in[UVC_IN_EP & 0xFU].is_used = 1U; + pdev->ep_in[UVC_IN_EP & 0xFU].maxpacket = UVC_ISO_FS_MPS; + } + + /* Init physical Interface components */ + ((USBD_VIDEO_ItfTypeDef *)pdev->pUserData_UVC)->Init(); + + /* Init Xfer states */ + hVIDEO->interface = 0U; + + /* Some calls to unused variables, to comply with MISRA-C 2012 rules */ + UNUSED(USBD_VIDEO_CfgDesc); + UNUSED(cfgidx); + + /* Exit with no error code */ + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_VIDEO_DeInit + * DeInitialize the VIDEO layer + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_VIDEO_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + UNUSED(cfgidx); + + /* Check if the video structure pointer is valid */ + if (pdev->pClassData_UVC == NULL) + { + return (uint8_t)USBD_FAIL; + } + + /* Close EP IN */ + (void)USBD_LL_CloseEP(pdev, UVC_IN_EP); + pdev->ep_in[UVC_IN_EP & 0xFU].is_used = 0U; + + /* DeInit physical Interface components */ + ((USBD_VIDEO_ItfTypeDef *)pdev->pUserData_UVC)->DeInit(); +#if (0) + USBD_free(pdev->pClassData_UVC); +#endif + pdev->pClassData_UVC = NULL; + + /* Exit with no error code */ + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_VIDEO_Setup + * Handle the VIDEO specific requests + * @param pdev: instance + * @param req: usb requests + * @retval status + */ +static uint8_t USBD_VIDEO_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_VIDEO_HandleTypeDef *hVIDEO = (USBD_VIDEO_HandleTypeDef *)pdev->pClassData_UVC; + uint8_t ret = (uint8_t)USBD_OK; + uint16_t len = 0U; + uint8_t *pbuf = NULL; + uint16_t status_info = 0U; + + switch (req->bmRequest & USB_REQ_TYPE_MASK) + { + /* Class Requests -------------------------------*/ + case USB_REQ_TYPE_CLASS: + switch (req->bRequest) + { + case UVC_GET_CUR: + case UVC_GET_DEF: + case UVC_GET_MIN: + case UVC_GET_MAX: + VIDEO_REQ_GetCurrent(pdev, req); + break; + case UVC_GET_RES: + case UVC_GET_LEN: + case UVC_GET_INFO: + break; + case UVC_SET_CUR: + VIDEO_REQ_SetCurrent(pdev, req); + break; + default: + (void)USBD_CtlError(pdev, req); + ret = (uint8_t)USBD_FAIL; + break; + } + break; + + /* Standard Requests -------------------------------*/ + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) + { + case USB_REQ_GET_STATUS: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U); + } + else + { + USBD_CtlError(pdev, req); + ret = (uint8_t)USBD_FAIL; + } + break; + + case USB_REQ_GET_DESCRIPTOR: + if ((req->wValue >> 8) == CS_DEVICE) + { + pbuf = USBD_VIDEO_CfgDesc + 18; + len = MIN((uint16_t)USB_CONF_DESC_SIZE, (uint16_t)req->wLength); + } + (void)USBD_CtlSendData(pdev, pbuf, len); + break; + + case USB_REQ_GET_INTERFACE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + (void)USBD_CtlSendData(pdev, (uint8_t *)&hVIDEO->interface, 1U); + } + else + { + USBD_CtlError(pdev, req); + ret = (uint8_t)USBD_FAIL; + } + break; + + case USB_REQ_SET_INTERFACE: + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + if (req->wValue <= USBD_MAX_NUM_INTERFACES) + { + hVIDEO->interface = LOBYTE(req->wValue); + if (hVIDEO->interface == 1U) + { + /* Start Streaming (First endpoint writing will be done on next SOF) */ + (void)USBD_LL_FlushEP(pdev, UVC_IN_EP); + hVIDEO->uvc_state = UVC_PLAY_STATUS_READY; + } + else + { + /* Stop Streaming */ + hVIDEO->uvc_state = UVC_PLAY_STATUS_STOP; + (void)USBD_LL_FlushEP(pdev, UVC_IN_EP); + } + } + else + { + /* Call the error management function (command will be NAKed) */ + USBD_CtlError(pdev, req); + ret = (uint8_t)USBD_FAIL; + } + } + else + { + USBD_CtlError(pdev, req); + ret = (uint8_t)USBD_FAIL; + } + break; + + case USB_REQ_CLEAR_FEATURE: + break; + + default: + USBD_CtlError(pdev, req); + ret = (uint8_t)USBD_FAIL; + break; + } + break; + + default: + USBD_CtlError(pdev, req); + ret = (uint8_t)USBD_FAIL; + break; + } + + return ret; +} + +/** + * @brief USBD_VIDEO_DataIn + * handle data IN Stage + * @param pdev: device instance + * @param epnum: endpoint index + * @retval status + */ +static uint8_t USBD_VIDEO_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + USBD_VIDEO_HandleTypeDef *hVIDEO = (USBD_VIDEO_HandleTypeDef *)pdev->pClassData_UVC; + static uint8_t packet[UVC_PACKET_SIZE + (UVC_HEADER_PACKET_CNT * 2U)] = {0x00U}; + static uint8_t *Pcktdata = packet; + static uint16_t PcktIdx = 0U; + static uint16_t PcktSze = UVC_PACKET_SIZE; + static uint8_t payload_header[2] = {0x02U, 0x00U}; + uint8_t i = 0U; + uint32_t RemainData, DataOffset = 0U; + + /* Check if the Streaming has already been started */ + if (hVIDEO->uvc_state == UVC_PLAY_STATUS_STREAMING) + { + /* Get the current packet buffer, index and size from the application layer */ + ((USBD_VIDEO_ItfTypeDef *)pdev->pUserData_UVC)->Data(&Pcktdata, &PcktSze, &PcktIdx); + + /* Check if end of current image has been reached */ + if (PcktSze > 2U) + { + /* Check if this is the first packet in current image */ + if (PcktIdx == 0U) + { + /* Set the packet start index */ + payload_header[1] ^= 0x01U; + } + + RemainData = PcktSze; + + /* fill the Transmit buffer */ + while (RemainData > 0U) + { + packet[((DataOffset + 0U) * i)] = payload_header[0]; + packet[((DataOffset + 0U) * i) + 1U] = payload_header[1]; + if (RemainData > pdev->ep_in[UVC_IN_EP & 0xFU].maxpacket) + { + DataOffset = pdev->ep_in[UVC_IN_EP & 0xFU].maxpacket; + (void)USBD_memcpy((packet + ((DataOffset + 0U) * i) + 2U), + Pcktdata + ((DataOffset - 2U) * i), (DataOffset - 2U)); + + RemainData -= DataOffset; + i++; + } + else + { + (void)USBD_memcpy((packet + ((DataOffset + 0U) * i) + 2U), + Pcktdata + ((DataOffset - 2U) * i), (RemainData - 2U)); + + RemainData = 0U; + } + } + } + else + { + /* Add the packet header */ + packet[0] = payload_header[0]; + packet[1] = payload_header[1]; + } + + /* Transmit the packet on Endpoint */ + (void)USBD_LL_Transmit(pdev, (uint8_t)(epnum | 0x80U), + (uint8_t *)&packet, (uint32_t)PcktSze); + } + + /* Exit with no error code */ + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_VIDEO_SOF + * handle SOF event + * @param pdev: device instance + * @retval status + */ +static uint8_t USBD_VIDEO_SOF(USBD_HandleTypeDef *pdev) +{ + USBD_VIDEO_HandleTypeDef *hVIDEO = (USBD_VIDEO_HandleTypeDef *)pdev->pClassData_UVC; + uint8_t payload[2] = {0x02U, 0x00U}; + + /* Check if the Streaming has already been started by SetInterface AltSetting 1 */ + if (hVIDEO->uvc_state == UVC_PLAY_STATUS_READY) + { + /* Transmit the first packet indicating that Streaming is starting */ + (void)USBD_LL_Transmit(pdev, UVC_IN_EP, (uint8_t *)payload, 2U); + + /* Enable Streaming state */ + hVIDEO->uvc_state = UVC_PLAY_STATUS_STREAMING; + } + + /* Exit with no error code */ + return (uint8_t)USBD_OK; +} + +/** + * @brief USBD_VIDEO_IsoINIncomplete + * handle data ISO IN Incomplete event + * @param pdev: device instance + * @param epnum: endpoint index + * @retval status + */ +static uint8_t USBD_VIDEO_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + UNUSED(pdev); + UNUSED(epnum); + + return (uint8_t)USBD_OK; +} + +/** + * @brief VIDEO_Req_GetCurrent + * Handles the GET_CUR VIDEO control request. + * @param pdev: instance + * @param req: setup class request + * @retval status + */ +static void VIDEO_REQ_GetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_VIDEO_HandleTypeDef *hVIDEO; + hVIDEO = (USBD_VIDEO_HandleTypeDef *)(pdev->pClassData_UVC); + static __IO uint8_t EntityStatus[8] = {0}; + + /* Reset buffer to zeros */ + (void)USBD_memset(hVIDEO->control.data, 0, USB_MAX_EP0_SIZE); + + /* Manage Video Control interface requests */ + if (LOBYTE(req->wIndex) == UVC_VC_IF_NUM) + { + if (HIBYTE(req->wValue) == 0x02U) + { + /* Get the status of the current requested Entity */ + EntityStatus[0] = 0x06U; + + /* Send current status */ + (void)USBD_CtlSendData(pdev, (uint8_t *)&EntityStatus, 1U); + } + else + { + /* Unknown request */ + USBD_CtlError(pdev, req); + } + } + /* Manage Video Streaming interface requests */ + else + { + if (LOBYTE(req->wValue) == (uint8_t)VS_PROBE_CONTROL) + { + /* Update bPreferedVersion, bMinVersion and bMaxVersion which must be set only by Device */ + video_Probe_Control.bPreferedVersion = 0x00U; + video_Probe_Control.bMinVersion = 0x00U; + video_Probe_Control.bMaxVersion = 0x00U; + video_Probe_Control.dwMaxVideoFrameSize = UVC_MAX_FRAME_SIZE; + + video_Probe_Control.dwClockFrequency = 0x02DC6C00U; + + if (pdev->dev_speed == USBD_SPEED_HIGH) + { + video_Probe_Control.dwFrameInterval = (UVC_INTERVAL(UVC_CAM_FPS_HS)); + video_Probe_Control.dwMaxPayloadTransferSize = UVC_ISO_HS_MPS; + } + else + { + video_Probe_Control.dwFrameInterval = (UVC_INTERVAL(UVC_CAM_FPS_FS)); + video_Probe_Control.dwMaxPayloadTransferSize = UVC_ISO_FS_MPS; + } + + /* Probe Request */ + (void)USBD_CtlSendData(pdev, (uint8_t *)&video_Probe_Control, + MIN(req->wLength, sizeof(USBD_VideoControlTypeDef))); + } + else if (LOBYTE(req->wValue) == (uint8_t)VS_COMMIT_CONTROL) + { + if (pdev->dev_speed == USBD_SPEED_HIGH) + { + video_Commit_Control.dwFrameInterval = (UVC_INTERVAL(UVC_CAM_FPS_HS)); + video_Commit_Control.dwMaxPayloadTransferSize = UVC_ISO_HS_MPS; + } + else + { + video_Commit_Control.dwFrameInterval = (UVC_INTERVAL(UVC_CAM_FPS_FS)); + video_Commit_Control.dwMaxPayloadTransferSize = UVC_ISO_FS_MPS; + } + + /* Commit Request */ + (void)USBD_CtlSendData(pdev, (uint8_t *)&video_Commit_Control, + MIN(req->wLength, sizeof(USBD_VideoControlTypeDef))); + } + else + { + /* Send the current state */ + (void)USBD_CtlSendData(pdev, hVIDEO->control.data, + MIN(req->wLength, USB_MAX_EP0_SIZE)); + } + } +} + +/** + * @brief VIDEO_Req_SetCurrent + * Handles the SET_CUR VIDEO control request. + * @param pdev: instance + * @param req: setup class request + * @retval status + */ +static void VIDEO_REQ_SetCurrent(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) +{ + USBD_VIDEO_HandleTypeDef *hVIDEO = (USBD_VIDEO_HandleTypeDef *)(pdev->pClassData_UVC); + + /* Check that the request has control data */ + if (req->wLength > 0U) + { + /* Prepare the reception of the buffer over EP0 */ + if (LOBYTE(req->wValue) == (uint8_t)VS_PROBE_CONTROL) + { + /* Probe Request */ + (void)USBD_CtlPrepareRx(pdev, (uint8_t *)&video_Probe_Control, + MIN(req->wLength, sizeof(USBD_VideoControlTypeDef))); + } + else if (LOBYTE(req->wValue) == (uint8_t)VS_COMMIT_CONTROL) + { + /* Commit Request */ + (void)USBD_CtlPrepareRx(pdev, (uint8_t *)&video_Commit_Control, + MIN(req->wLength, sizeof(USBD_VideoControlTypeDef))); + } + else + { + /* Prepare the reception of the buffer over EP0 */ + (void)USBD_CtlPrepareRx(pdev, hVIDEO->control.data, + MIN(req->wLength, USB_MAX_EP0_SIZE)); + } + } +} + +/** + * @brief USBD_VIDEO_GetFSCfgDesc + * return configuration descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_VIDEO_GetFSCfgDesc(uint16_t *length) +{ + USBD_EpDescTypedef *pEpDesc = USBD_VIDEO_GetEpDesc(USBD_VIDEO_CfgDesc, UVC_IN_EP); + USBD_VIDEO_VSFrameDescTypeDef *pVSFrameDesc = USBD_VIDEO_GetVSFrameDesc(USBD_VIDEO_CfgDesc); + + if (pEpDesc != NULL) + { + pEpDesc->wMaxPacketSize = UVC_ISO_FS_MPS; + } + + if (pVSFrameDesc != NULL) + { + pVSFrameDesc->dwMinBitRate = UVC_MIN_BIT_RATE(UVC_CAM_FPS_FS); + pVSFrameDesc->dwMaxBitRate = UVC_MAX_BIT_RATE(UVC_CAM_FPS_FS); + pVSFrameDesc->dwDefaultFrameInterval = UVC_INTERVAL(UVC_CAM_FPS_FS); + pVSFrameDesc->dwMinFrameInterval = UVC_INTERVAL(UVC_CAM_FPS_FS); + } + + *length = (uint16_t)(sizeof(USBD_VIDEO_CfgDesc)); + return USBD_VIDEO_CfgDesc; +} + +/** + * @brief USBD_VIDEO_GetHSCfgDesc + * return configuration descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_VIDEO_GetHSCfgDesc(uint16_t *length) +{ + USBD_EpDescTypedef *pEpDesc = USBD_VIDEO_GetEpDesc(USBD_VIDEO_CfgDesc, UVC_IN_EP); + USBD_VIDEO_VSFrameDescTypeDef *pVSFrameDesc = USBD_VIDEO_GetVSFrameDesc(USBD_VIDEO_CfgDesc); + + if (pEpDesc != NULL) + { + pEpDesc->wMaxPacketSize = UVC_ISO_HS_MPS; + } + + if (pVSFrameDesc != NULL) + { + pVSFrameDesc->dwMinBitRate = UVC_MIN_BIT_RATE(UVC_CAM_FPS_HS); + pVSFrameDesc->dwMaxBitRate = UVC_MAX_BIT_RATE(UVC_CAM_FPS_HS); + pVSFrameDesc->dwDefaultFrameInterval = UVC_INTERVAL(UVC_CAM_FPS_HS); + pVSFrameDesc->dwMinFrameInterval = UVC_INTERVAL(UVC_CAM_FPS_HS); + } + + *length = (uint16_t)(sizeof(USBD_VIDEO_CfgDesc)); + return USBD_VIDEO_CfgDesc; +} + +/** + * @brief USBD_VIDEO_GetOtherSpeedCfgDesc + * return configuration descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_VIDEO_GetOtherSpeedCfgDesc(uint16_t *length) +{ + USBD_EpDescTypedef *pEpDesc = USBD_VIDEO_GetEpDesc(USBD_VIDEO_CfgDesc, UVC_IN_EP); + USBD_VIDEO_VSFrameDescTypeDef *pVSFrameDesc = USBD_VIDEO_GetVSFrameDesc(USBD_VIDEO_CfgDesc); + + if (pEpDesc != NULL) + { + pEpDesc->wMaxPacketSize = UVC_ISO_FS_MPS; + } + + if (pVSFrameDesc != NULL) + { + pVSFrameDesc->dwMinBitRate = UVC_MIN_BIT_RATE(UVC_CAM_FPS_FS); + pVSFrameDesc->dwMaxBitRate = UVC_MAX_BIT_RATE(UVC_CAM_FPS_FS); + pVSFrameDesc->dwDefaultFrameInterval = UVC_INTERVAL(UVC_CAM_FPS_FS); + pVSFrameDesc->dwMinFrameInterval = UVC_INTERVAL(UVC_CAM_FPS_FS); + } + + *length = (uint16_t)(sizeof(USBD_VIDEO_CfgDesc)); + return USBD_VIDEO_CfgDesc; +} + +/** + * @brief DeviceQualifierDescriptor + * return Device Qualifier descriptor + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_VIDEO_GetDeviceQualifierDesc(uint16_t *length) +{ + *length = (uint16_t)(sizeof(USBD_VIDEO_DeviceQualifierDesc)); + return USBD_VIDEO_DeviceQualifierDesc; +} + +/** + * @brief USBD_VIDEO_GetNextDesc + * This function return the next descriptor header + * @param buf: Buffer where the descriptor is available + * @param ptr: data pointer inside the descriptor + * @retval next header + */ +static USBD_VIDEO_DescHeader_t *USBD_VIDEO_GetNextDesc(uint8_t *pbuf, uint16_t *ptr) +{ + USBD_VIDEO_DescHeader_t *pnext = (USBD_VIDEO_DescHeader_t *)(void *)pbuf; + + *ptr += pnext->bLength; + pnext = (USBD_VIDEO_DescHeader_t *)(void *)(pbuf + pnext->bLength); + + return (pnext); +} + +/** + * @brief USBD_VIDEO_GetVSFrameDesc + * This function return the Video Endpoint descriptor + * @param pdev: device instance + * @param pConfDesc: pointer to Bos descriptor + * @retval pointer to video endpoint descriptor + */ +static void *USBD_VIDEO_GetVSFrameDesc(uint8_t *pConfDesc) +{ + USBD_VIDEO_DescHeader_t *pdesc = (USBD_VIDEO_DescHeader_t *)(void *)pConfDesc; + USBD_ConfigDescTypedef *desc = (USBD_ConfigDescTypedef *)(void *)pConfDesc; + USBD_VIDEO_VSFrameDescTypeDef *pVSFrameDesc = NULL; + uint16_t ptr; + + if (desc->wTotalLength > desc->bLength) + { + ptr = desc->bLength; + + while (ptr < desc->wTotalLength) + { + pdesc = USBD_VIDEO_GetNextDesc((uint8_t *)pdesc, &ptr); + + if (((pdesc->bDescriptorSubType == VS_FRAME_MJPEG) || + (pdesc->bDescriptorSubType == VS_FRAME_UNCOMPRESSED)) && + (pdesc->bLength == VS_FRAME_DESC_SIZE)) + { + pVSFrameDesc = (USBD_VIDEO_VSFrameDescTypeDef *)(void *)pdesc; + break; + } + } + } + + return (void *)pVSFrameDesc; +} + +/** + * @brief USBD_VIDEO_GetEpDesc + * This function return the Video Endpoint descriptor + * @param pdev: device instance + * @param pConfDesc: pointer to Bos descriptor + * @param EpAddr: endpoint address + * @retval pointer to video endpoint descriptor + */ +static void *USBD_VIDEO_GetEpDesc(uint8_t *pConfDesc, uint8_t EpAddr) +{ + USBD_VIDEO_DescHeader_t *pdesc = (USBD_VIDEO_DescHeader_t *)(void *)pConfDesc; + USBD_ConfigDescTypedef *desc = (USBD_ConfigDescTypedef *)(void *)pConfDesc; + USBD_EpDescTypedef *pEpDesc = NULL; + uint16_t ptr; + + if (desc->wTotalLength > desc->bLength) + { + ptr = desc->bLength; + + while (ptr < desc->wTotalLength) + { + pdesc = USBD_VIDEO_GetNextDesc((uint8_t *)pdesc, &ptr); + + if (pdesc->bDescriptorType == USB_DESC_TYPE_ENDPOINT) + { + pEpDesc = (USBD_EpDescTypedef *)(void *)pdesc; + + if (pEpDesc->bEndpointAddress == EpAddr) + { + break; + } + else + { + pEpDesc = NULL; + } + } + } + } + + return (void *)pEpDesc; +} + +/** + * @brief USBD_VIDEO_RegisterInterface + * @param pdev: instance + * @param fops: VIDEO interface callback + * @retval status + */ +uint8_t USBD_VIDEO_RegisterInterface(USBD_HandleTypeDef *pdev, USBD_VIDEO_ItfTypeDef *fops) +{ + /* Check if the FOPS pointer is valid */ + if (fops == NULL) + { + return (uint8_t)USBD_FAIL; + } + + /* Assign the FOPS pointer */ + pdev->pUserData_UVC = fops; + + /* Exit with no error code */ + return (uint8_t)USBD_OK; +} + +void USBD_Update_UVC_DESC(uint8_t *desc, uint8_t vc_itf, uint8_t vs_itf, uint8_t in_ep, uint8_t str_idx) +{ +#ifdef USBD_UVC_FORMAT_UNCOMPRESSED +#define _OFFSET 44 +#else +#define _OFFSET 22 +#endif + + desc[11] = vc_itf; + desc[16] = str_idx; + desc[19] = vc_itf; + desc[38] = vs_itf; + desc[58] = vs_itf; + desc[71] = in_ep; + desc[100 + _OFFSET] = vs_itf; + desc[109 + _OFFSET] = in_ep; + + UVC_IN_EP = in_ep; + UVC_VC_IF_NUM = vc_itf; + UVC_VS_IF_NUM = vs_itf; + UVC_STR_DESC_IDX = str_idx; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/USBD_Test/USBD_Test.ioc_bkp b/USBD_Test/USBD_Test.ioc_bkp new file mode 100644 index 0000000..02238f7 --- /dev/null +++ b/USBD_Test/USBD_Test.ioc_bkp @@ -0,0 +1,246 @@ +#MicroXplorer Configuration settings - do not modify +Mcu.Family=STM32H7 +RCC.DIVQ2Freq_Value=200000000 +AL94.I-CUBE-USBD-COMPOSITE.1.0.2.CompositeCcUSBJjCOMPOSITEJjHIDIiCUSTOM=true +NVIC.OTG_HS_IRQn=true\:0\:0\:false\:false\:true\:true\:true +ProjectManager.MainLocation=Core/Src +PH0-OSC_IN.Signal=RCC_OSC_IN +RCC.CDCPREFreq_Value=72000000 +RCC.SAI1Freq_Value=48000000 +RCC.CortexFreq_Value=72000000 +ProjectManager.KeepUserCode=true +Mcu.UserName=STM32H7B3LIHxQ +PB10.Mode=Device_HS +RCC.PLLFRACN=0 +ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false,3-MX_USB_OTG_HS_PCD_Init-USB_OTG_HS-false-HAL-true,4-MX_USART1_UART_Init-USART1-false-HAL-true,0-MX_CORTEX_M7_Init-CORTEX_M7-false-HAL-true +RCC.RTCFreq_Value=32768 +AL94.I-CUBE-USBD-COMPOSITE.1.0.2.CompositeCcUSBJjCOMPOSITEJjMSCIiBOT=true +RCC.PLL2FRACN=0 +RCC.CpuClockFreq_Value=72000000 +RCC.VCO2OutputFreq_Value=400000000 +USART1.IPParameters=VirtualMode-Asynchronous +PB11.Signal=USB_OTG_HS_ULPI_D4 +PB13.Signal=USB_OTG_HS_ULPI_D6 +PinOutPanel.RotationAngle=0 +USB_OTG_HS.VirtualMode-Device_HS=Device_HS +RCC.MCO1PinFreq_Value=24000000 +RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK +ProjectManager.StackSize=0x400 +RCC.AHB4Freq_Value=72000000 +RCC.VCOInput3Freq_Value=1000000 +RCC.SPI123CLockSelection=RCC_SPI123CLKSOURCE_CLKP +RCC.LPTIM1Freq_Value=72000000 +AL94.I-CUBE-USBD-COMPOSITE.1.0.2._USBD_USE_HID_CUSTOM=true +Mcu.IP4=USART1 +AL94.I-CUBE-USBD-COMPOSITE.1.0.2.CompositeCcUSBJjCOMPOSITEJjPRINTER=true +RCC.SAI2BFreq_Value=48000000 +Mcu.IP5=USB_OTG_HS +NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false +Mcu.IP2=RCC +Mcu.IP3=SYS +PI11.Mode=Device_HS +Mcu.IP0=CORTEX_M7 +Mcu.IP1=NVIC +Mcu.UserConstants= +RCC.DIVP3Freq_Value=11294117.647058824 +RCC.SDMMCFreq_Value=100000000 +Mcu.ThirdPartyNb=1 +RCC.HCLKFreq_Value=72000000 +RCC.I2C4Freq_Value=72000000 +Mcu.IPNb=6 +ProjectManager.PreviousToolchain= +PB6.Signal=USART1_TX +RCC.SPDIFRXFreq_Value=48000000 +AL94.I-CUBE-USBD-COMPOSITE.1.0.2.CompositeCcUSBJjCOMPOSITEJjCDCIiRNDIS=true +PB6.Mode=Asynchronous +RCC.DIVQ3Freq_Value=96000000 +Mcu.Pin6=PH1-OSC_OUT +Mcu.Pin7=PC0 +Mcu.Pin8=PB1 +Mcu.Pin9=PH4 +AL94.I-CUBE-USBD-COMPOSITE.1.0.2.CompositeCcUSBJjCOMPOSITEJjUACIiMIC=true +PH0-OSC_IN.Mode=HSE-External-Oscillator +Mcu.Pin0=PB6 +Mcu.Pin1=PB7 +GPIO.groupedBy=Group By Peripherals +Mcu.Pin2=PB5 +Mcu.Pin3=PI11 +Mcu.Pin4=PA8 +Mcu.Pin5=PH0-OSC_IN +ProjectManager.ProjectBuild=false +RCC.DIVR3Freq_Value=96000000 +NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false +NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false +RCC.DIVM3=24 +RCC.DIVM2=12 +NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true +RCC.DIVM1=2 +RCC.RTCClockSelection=RCC_RTCCLKSOURCE_LSE +RCC.RCC_MCO1Source=RCC_MCO1SOURCE_HSE +RCC.DFSDM2Freq_Value=72000000 +ProjectManager.FirmwarePackage=STM32Cube FW_H7 V1.9.0 +MxDb.Version=DB.6.0.21 +Mcu.ThirdParty0=AL94.I-CUBE-USBD-COMPOSITE.1.0.2 +RCC.DIVP1Freq_Value=72000000 +ProjectManager.BackupPrevious=false +RCC.FMCFreq_Value=100000000 +VP_AL94.I-CUBE-USBD-COMPOSITE_VS_USBJjComposite_1.0.0_1.0.2.Mode=USBJjComposite +RCC.DFSDM2ACLkFreq_Value=72000000 +PB5.Mode=Device_HS +RCC.USART16Freq_Value=72000000 +File.Version=6 +PB7.Signal=USART1_RX +AL94.I-CUBE-USBD-COMPOSITE.1.0.2._USBD_USE_CDC_ACM=true +PA8.Signal=RCC_MCO_1 +AL94.I-CUBE-USBD-COMPOSITE.1.0.2.CompositeCcUSBJjCOMPOSITEJjCOMPOSITE=true +NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false +USB_OTG_HS.IPParameters=VirtualMode-Device_HS +AL94.I-CUBE-USBD-COMPOSITE.1.0.2.CompositeCcUSBJjCOMPOSITEJjCDCIiECM=true +RCC.DIVR2Freq_Value=100000000 +ProjectManager.HalAssertFull=false +RCC.DIVP2Freq_Value=200000000 +ProjectManager.ProjectName=USBD_Test +AL94.I-CUBE-USBD-COMPOSITE.1.0.2.CompositeCcUSBJjCOMPOSITEJjHIDIiMOUSE=true +RCC.APB3Freq_Value=72000000 +PH1-OSC_OUT.Mode=HSE-External-Oscillator +RCC.MCO2PinFreq_Value=72000000 +Mcu.Package=TFBGA225 +PB1.Signal=USB_OTG_HS_ULPI_D2 +AL94.I-CUBE-USBD-COMPOSITE.1.0.2.CompositeCcUSBJjCOMPOSITEJjDFU=true +PB12.Mode=Device_HS +AL94.I-CUBE-USBD-COMPOSITE.1.0.2._USBD_USE_UAC_MIC=true +RCC.PLL3FRACN=0 +RCC.SDMMC1CLockSelection=RCC_SDMMCCLKSOURCE_PLL2 +AL94.I-CUBE-USBD-COMPOSITE.1.0.2._USBD_USE_HID_KEYBOARD=true +ProjectManager.ToolChainLocation= +VP_SYS_VS_Systick.Signal=SYS_VS_Systick +AL94.I-CUBE-USBD-COMPOSITE.1.0.2.CompositeCcUSBJjCOMPOSITEJjUACIiSPKR=true +RCC.DFSDMFreq_Value=72000000 +RCC.DIVR1Freq_Value=36000000 +RCC.TraceFreq_Value=64000000 +RCC.APB4Freq_Value=72000000 +AL94.I-CUBE-USBD-COMPOSITE.1.0.2._USBD_USE_DFU=true +RCC.CECFreq_Value=32000 +NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false +AL94.I-CUBE-USBD-COMPOSITE.1.0.2.CompositeCcUSBJjCOMPOSITEJjHIDIiKEYBOARD=true +RCC.LPUART1Freq_Value=72000000 +PB13.Mode=Device_HS +PI11.Signal=USB_OTG_HS_ULPI_DIR +ProjectManager.CustomerFirmwarePackage= +RCC.SupplySource=PWR_DIRECT_SMPS_SUPPLY +RCC.Tim2OutputFreq_Value=72000000 +RCC.DFSDMACLkFreq_Value=48000000 +RCC.VCO3OutputFreq_Value=192000000 +PA3.Signal=USB_OTG_HS_ULPI_D0 +PA5.Mode=Device_HS +AL94.I-CUBE-USBD-COMPOSITE.1.0.2.CompositeCcUSBJjCOMPOSITEJjUVC=true +RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSE +ProjectManager.ProjectFileName=USBD_Test.ioc +RCC.DIVQ1=3 +Mcu.PinsNb=19 +ProjectManager.NoMain=false +RCC.SWPMI1Freq_Value=72000000 +RCC.DIVP3=17 +AL94.I-CUBE-USBD-COMPOSITE.1.0.2._USBD_USE_UAC_SPKR=true +ProjectManager.DefaultFWLocation=true +ProjectManager.DeletePrevious=true +PC0.Signal=USB_OTG_HS_ULPI_STP +RCC.QSPIFreq_Value=100000000 +boardIOC=true +AL94.I-CUBE-USBD-COMPOSITE.1.0.2._USBD_USE_UVC=true +RCC.PWR_Regulator_Voltage_Scale=PWR_REGULATOR_VOLTAGE_SCALE0 +PinOutPanel.CurrentBGAView=Top +RCC.FamilyName=M +PC0.Mode=Device_HS +RCC.SPI6Freq_Value=72000000 +USART1.VirtualMode-Asynchronous=VM_ASYNC +PA3.Mode=Device_HS +RCC.USART234578Freq_Value=72000000 +RCC.SPI45Freq_Value=72000000 +RCC.Tim1OutputFreq_Value=72000000 +PH4.Signal=USB_OTG_HS_ULPI_NXT +RCC.SPI123Freq_Value=64000000 +PB11.Mode=Device_HS +ProjectManager.TargetToolchain=STM32CubeIDE +RCC.VCO1OutputFreq_Value=144000000 +AL94.I-CUBE-USBD-COMPOSITE.1.0.2._USBD_USE_MSC=true +RCC.DIVN3=192 +RCC.DIVN2=200 +RCC.AXIClockFreq_Value=72000000 +RCC.DIVN1=12 +ProjectManager.RegisterCallBack= +AL94.I-CUBE-USBD-COMPOSITE.1.0.2.USBJjComposite_Checked=true +RCC.USBFreq_Value=48000000 +RCC.CKPERFreq_Value=64000000 +AL94.I-CUBE-USBD-COMPOSITE.1.0.2.IPParameters=_USBD_USE_HS,_USBD_USE_CDC_ACM,_USBD_USE_CDC_RNDIS,_USBD_USE_CDC_ECM,_USBD_USE_HID_MOUSE,_USBD_USE_HID_KEYBOARD,_USBD_USE_HID_CUSTOM,_USBD_USE_UAC_MIC,_USBD_USE_UAC_SPKR,_USBD_USE_UVC,_USBD_USE_MSC,_USBD_USE_DFU,_USBD_USE_PRNTR,CompositeCcUSBJjCOMPOSITEJjCore,CompositeCcUSBJjCOMPOSITEJjCDCIiACM,CompositeCcUSBJjCOMPOSITEJjCDCIiRNDIS,CompositeCcUSBJjCOMPOSITEJjHIDIiMOUSE,CompositeCcUSBJjCOMPOSITEJjHIDIiKEYBOARD,CompositeCcUSBJjCOMPOSITEJjHIDIiCUSTOM,CompositeCcUSBJjCOMPOSITEJjMSCIiBOT,CompositeCcUSBJjCOMPOSITEJjUACIiMIC,CompositeCcUSBJjCOMPOSITEJjUACIiSPKR,CompositeCcUSBJjCOMPOSITEJjUVC,CompositeCcUSBJjCOMPOSITEJjDFU,CompositeCcUSBJjCOMPOSITEJjCDCIiECM,CompositeCcUSBJjCOMPOSITEJjCOMPOSITE,CompositeCcUSBJjCOMPOSITEJjPRINTER +PB10.Signal=USB_OTG_HS_ULPI_D3 +PA5.Signal=USB_OTG_HS_ULPI_CK +PB0.Mode=Device_HS +board=STM32H7B3I-DK +AL94.I-CUBE-USBD-COMPOSITE.1.0.2._USBD_USE_PRNTR=true +ProjectManager.LastFirmware=false +RCC.VCOInput1Freq_Value=12000000 +RCC.AHB12Freq_Value=72000000 +RCC.APB2Freq_Value=72000000 +MxCube.Version=6.2.1 +AL94.I-CUBE-USBD-COMPOSITE.1.0.2.CompositeCcUSBJjCOMPOSITEJjCore=true +RCC.FMCCLockSelection=RCC_FMCCLKSOURCE_PLL2 +RCC.FDCANFreq_Value=48000000 +RCC.RNGFreq_Value=48000000 +RCC.ADCFreq_Value=200000000 +VP_SYS_VS_Systick.Mode=SysTick +PH1-OSC_OUT.Signal=RCC_OSC_OUT +NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false +AL94.I-CUBE-USBD-COMPOSITE.1.0.2.CompositeCcUSBJjCOMPOSITEJjCDCIiACM=true +ProjectManager.FreePins=false +RCC.IPParameters=ADCFreq_Value,AHB12Freq_Value,AHB4Freq_Value,APB1Freq_Value,APB2Freq_Value,APB3Freq_Value,APB4Freq_Value,AXIClockFreq_Value,CDCPREFreq_Value,CECFreq_Value,CKPERFreq_Value,CortexFreq_Value,CpuClockFreq_Value,DFSDM2ACLkFreq_Value,DFSDM2Freq_Value,DFSDMACLkFreq_Value,DFSDMFreq_Value,DIVM1,DIVM2,DIVM3,DIVN1,DIVN2,DIVN3,DIVP1Freq_Value,DIVP2Freq_Value,DIVP3,DIVP3Freq_Value,DIVQ1,DIVQ1Freq_Value,DIVQ2Freq_Value,DIVQ3Freq_Value,DIVR1,DIVR1Freq_Value,DIVR2,DIVR2Freq_Value,DIVR3Freq_Value,FDCANFreq_Value,FMCCLockSelection,FMCFreq_Value,FamilyName,HCLK3ClockFreq_Value,HCLKFreq_Value,I2C123Freq_Value,I2C4Freq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPTIM345Freq_Value,LPUART1Freq_Value,LTDCFreq_Value,MCO1PinFreq_Value,MCO2PinFreq_Value,PLL2FRACN,PLL3FRACN,PLLFRACN,PLLSourceVirtual,PWR_Regulator_Voltage_Scale,QSPICLockSelection,QSPIFreq_Value,RCC_MCO1Source,RNGFreq_Value,RTCClockSelection,RTCFreq_Value,SAI1Freq_Value,SAI2AFreq_Value,SAI2BFreq_Value,SDMMC1CLockSelection,SDMMCFreq_Value,SPDIFRXFreq_Value,SPI123CLockSelection,SPI123Freq_Value,SPI45Freq_Value,SPI6Freq_Value,SWPMI1Freq_Value,SYSCLKFreq_VALUE,SYSCLKSource,SupplySource,Tim1OutputFreq_Value,Tim2OutputFreq_Value,TraceFreq_Value,USART16Freq_Value,USART234578Freq_Value,USBFreq_Value,VCO1OutputFreq_Value,VCO2OutputFreq_Value,VCO3OutputFreq_Value,VCOInput1Freq_Value,VCOInput2Freq_Value,VCOInput3Freq_Value +AL94.I-CUBE-USBD-COMPOSITE.1.0.2._USBD_USE_CDC_ECM=true +ProjectManager.AskForMigrate=true +Mcu.Name=STM32H7B3LIHxQ +RCC.LPTIM2Freq_Value=72000000 +PH4.Mode=Device_HS +ProjectManager.UnderRoot=true +ProjectManager.CoupleFile=true +RCC.SYSCLKFreq_VALUE=72000000 +PB5.Signal=USB_OTG_HS_ULPI_D7 +RCC.I2C123Freq_Value=72000000 +AL94.I-CUBE-USBD-COMPOSITE.1.0.2._USBD_USE_HID_MOUSE=true +NVIC.ForceEnableDMAVector=true +KeepUserPlacement=false +NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false +ProjectManager.CompilerOptimize=6 +RCC.QSPICLockSelection=RCC_OSPICLKSOURCE_PLL2 +PB7.Mode=Asynchronous +AL94.I-CUBE-USBD-COMPOSITE.1.0.2_SwParameter=CompositeCcUSBJjCOMPOSITEJjHIDIiCUSTOM\:true;CompositeCcUSBJjCOMPOSITEJjMSCIiBOT\:true;CompositeCcUSBJjCOMPOSITEJjCOMPOSITE\:true;CompositeCcUSBJjCOMPOSITEJjUACIiSPKR\:true;CompositeCcUSBJjCOMPOSITEJjUACIiMIC\:true;CompositeCcUSBJjCOMPOSITEJjHIDIiMOUSE\:true;CompositeCcUSBJjCOMPOSITEJjDFU\:true;CompositeCcUSBJjCOMPOSITEJjHIDIiKEYBOARD\:true;CompositeCcUSBJjCOMPOSITEJjCore\:true;CompositeCcUSBJjCOMPOSITEJjCDCIiECM\:true;CompositeCcUSBJjCOMPOSITEJjCDCIiRNDIS\:true;CompositeCcUSBJjCOMPOSITEJjCDCIiACM\:true;CompositeCcUSBJjCOMPOSITEJjUVC\:true;CompositeCcUSBJjCOMPOSITEJjPRINTER\:true; +ProjectManager.HeapSize=0x200 +Mcu.Pin15=PA3 +NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false +Mcu.Pin16=PB10 +PB1.Mode=Device_HS +Mcu.Pin13=PB0 +Mcu.Pin14=PB11 +RCC.LPTIM345Freq_Value=72000000 +ProjectManager.ComputerToolchain=false +Mcu.Pin17=VP_SYS_VS_Systick +Mcu.Pin18=VP_AL94.I-CUBE-USBD-COMPOSITE_VS_USBJjComposite_1.0.0_1.0.2 +RCC.LTDCFreq_Value=96000000 +NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 +Mcu.Pin11=PA5 +Mcu.Pin12=PB12 +Mcu.Pin10=PB13 +RCC.DIVQ1Freq_Value=48000000 +PA8.Mode=Clock-out-1 +AL94.I-CUBE-USBD-COMPOSITE.1.0.2._USBD_USE_CDC_RNDIS=true +AL94.I-CUBE-USBD-COMPOSITE.1.0.2._USBD_USE_HS=true +RCC.HCLK3ClockFreq_Value=72000000 +RCC.VCOInput2Freq_Value=2000000 +RCC.APB1Freq_Value=72000000 +RCC.DIVR2=4 +RCC.DIVR1=4 +PB0.Signal=USB_OTG_HS_ULPI_D1 +RCC.SAI2AFreq_Value=48000000 +ProjectManager.DeviceId=STM32H7B3LIHxQ +PB12.Signal=USB_OTG_HS_ULPI_D5 +ProjectManager.LibraryCopy=1 +VP_AL94.I-CUBE-USBD-COMPOSITE_VS_USBJjComposite_1.0.0_1.0.2.Signal=AL94.I-CUBE-USBD-COMPOSITE_VS_USBJjComposite_1.0.0_1.0.2 +isbadioc=false diff --git a/stm32_mw_usb_device/App/usbd_msc_if.c b/stm32_mw_usb_device/App/usbd_msc_if.c index 4b5f130..195cbec 100644 --- a/stm32_mw_usb_device/App/usbd_msc_if.c +++ b/stm32_mw_usb_device/App/usbd_msc_if.c @@ -64,7 +64,7 @@ uint8_t MSC_Storage[32*1024]; */ #define STORAGE_LUN_NBR 1 -#define STORAGE_BLK_NBR 100*1024/512 +#define STORAGE_BLK_NBR 32*1024/512 #define STORAGE_BLK_SIZ 512 /* USER CODE BEGIN PRIVATE_DEFINES */ diff --git a/stm32_mw_usb_device/Class/CDC_ACM/Src/usbd_cdc_acm.c b/stm32_mw_usb_device/Class/CDC_ACM/Src/usbd_cdc_acm.c index d5cbd30..b5f85d5 100644 --- a/stm32_mw_usb_device/Class/CDC_ACM/Src/usbd_cdc_acm.c +++ b/stm32_mw_usb_device/Class/CDC_ACM/Src/usbd_cdc_acm.c @@ -1968,15 +1968,15 @@ static uint8_t USBD_CDC_EP0_RxReady(USBD_HandleTypeDef *pdev) { USBD_CDC_ACM_HandleTypeDef *hcdc = NULL; - if (hcdc == NULL) - { - return (uint8_t)USBD_FAIL; - } - for (uint8_t i = 0; i < NUMBER_OF_CDC; i++) { hcdc = &CDC_ACM_Class_Data[i]; + if (hcdc == NULL) + { + return (uint8_t)USBD_FAIL; + } + if ((pdev->pUserData_CDC_ACM != NULL) && (hcdc->CmdOpCode != 0xFFU)) { ((USBD_CDC_ACM_ItfTypeDef *)pdev->pUserData_CDC_ACM)->Control(i, hcdc->CmdOpCode, (uint8_t *)hcdc->data[i], (uint16_t)hcdc->CmdLength);