1 /*
2  * This file is part of the MicroPython project, http://micropython.org/
3  */
4 
5 /**
6   ******************************************************************************
7   * @file    USB_Device/CDC_Standalone/Src/usbd_conf.c
8   * @author  MCD Application Team
9   * @version V1.0.1
10   * @date    26-February-2014
11   * @brief   This file implements the USB Device library callbacks and MSP
12   ******************************************************************************
13   * @attention
14   *
15   * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
16   *
17   * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
18   * You may not use this file except in compliance with the License.
19   * You may obtain a copy of the License at:
20   *
21   *        http://www.st.com/software_license_agreement_liberty_v2
22   *
23   * Unless required by applicable law or agreed to in writing, software
24   * distributed under the License is distributed on an "AS IS" BASIS,
25   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26   * See the License for the specific language governing permissions and
27   * limitations under the License.
28   *
29   ******************************************************************************
30   */
31 
32 #include "usbd_core.h"
33 #include "py/obj.h"
34 #include "py/mphal.h"
35 #include "irq.h"
36 #include "usb.h"
37 
38 #if MICROPY_HW_USB_FS || MICROPY_HW_USB_HS
39 
40 #if MICROPY_HW_USB_FS
41 PCD_HandleTypeDef pcd_fs_handle;
42 #endif
43 #if MICROPY_HW_USB_HS
44 PCD_HandleTypeDef pcd_hs_handle;
45 #endif
46 
47 #if !MICROPY_HW_USB_IS_MULTI_OTG
48 // The MCU has a single USB device-only instance
49 #define USB_OTG_FS USB
50 #endif
51 
52 /*******************************************************************************
53                        PCD BSP Routines
54 *******************************************************************************/
55 
56 /**
57   * @brief  Initializes the PCD MSP.
58   * @param  hpcd: PCD handle
59   * @retval None
60   */
HAL_PCD_MspInit(PCD_HandleTypeDef * hpcd)61 void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) {
62     if (hpcd->Instance == USB_OTG_FS) {
63         #if defined(STM32H7)
64         const uint32_t otg_alt = GPIO_AF10_OTG1_FS;
65         #elif defined(STM32L0)
66         const uint32_t otg_alt = GPIO_AF0_USB;
67         #elif defined(STM32L432xx)
68         const uint32_t otg_alt = GPIO_AF10_USB_FS;
69         #elif defined(STM32WB)
70         const uint32_t otg_alt = GPIO_AF10_USB;
71         #else
72         const uint32_t otg_alt = GPIO_AF10_OTG_FS;
73         #endif
74 
75         mp_hal_pin_config(pin_A11, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, otg_alt);
76         mp_hal_pin_config_speed(pin_A11, GPIO_SPEED_FREQ_VERY_HIGH);
77         mp_hal_pin_config(pin_A12, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, otg_alt);
78         mp_hal_pin_config_speed(pin_A12, GPIO_SPEED_FREQ_VERY_HIGH);
79 
80         #if defined(MICROPY_HW_USB_VBUS_DETECT_PIN)
81         // USB VBUS detect pin is always A9
82         mp_hal_pin_config(MICROPY_HW_USB_VBUS_DETECT_PIN, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0);
83         #endif
84 
85         #if defined(MICROPY_HW_USB_OTG_ID_PIN)
86         // USB ID pin is always A10
87         mp_hal_pin_config(MICROPY_HW_USB_OTG_ID_PIN, MP_HAL_PIN_MODE_ALT_OPEN_DRAIN, MP_HAL_PIN_PULL_UP, otg_alt);
88         #endif
89 
90         #if defined(STM32H7)
91         // Keep USB clock running during sleep or else __WFI() will disable the USB
92         __HAL_RCC_USB2_OTG_FS_CLK_SLEEP_ENABLE();
93         __HAL_RCC_USB2_OTG_FS_ULPI_CLK_SLEEP_DISABLE();
94         #endif
95 
96         // Enable USB FS Clocks
97         #if !MICROPY_HW_USB_IS_MULTI_OTG
98         __HAL_RCC_USB_CLK_ENABLE();
99         #else
100         __USB_OTG_FS_CLK_ENABLE();
101         #endif
102 
103         #if defined(STM32L4)
104         // Enable VDDUSB
105         if (__HAL_RCC_PWR_IS_CLK_DISABLED()) {
106             __HAL_RCC_PWR_CLK_ENABLE();
107             HAL_PWREx_EnableVddUSB();
108             __HAL_RCC_PWR_CLK_DISABLE();
109         } else {
110             HAL_PWREx_EnableVddUSB();
111         }
112         #endif
113 
114         // Configure and enable USB FS interrupt
115         #if defined(STM32L0)
116         NVIC_SetPriority(USB_IRQn, IRQ_PRI_OTG_FS);
117         HAL_NVIC_EnableIRQ(USB_IRQn);
118         #elif defined(STM32L432xx)
119         NVIC_SetPriority(USB_FS_IRQn, IRQ_PRI_OTG_FS);
120         HAL_NVIC_EnableIRQ(USB_FS_IRQn);
121         #elif defined(STM32WB)
122         NVIC_SetPriority(USB_LP_IRQn, IRQ_PRI_OTG_FS);
123         HAL_NVIC_EnableIRQ(USB_LP_IRQn);
124         #else
125         NVIC_SetPriority(OTG_FS_IRQn, IRQ_PRI_OTG_FS);
126         HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
127         #endif
128     }
129     #if MICROPY_HW_USB_HS
130     else if (hpcd->Instance == USB_OTG_HS) {
131         #if MICROPY_HW_USB_HS_IN_FS
132 
133         #if defined(STM32H7)
134         const uint32_t otg_alt = GPIO_AF12_OTG2_FS;
135         #else
136         const uint32_t otg_alt = GPIO_AF12_OTG_HS_FS;
137         #endif
138 
139         // Configure USB FS GPIOs
140         mp_hal_pin_config(pin_B14, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, otg_alt);
141         mp_hal_pin_config_speed(pin_B14, GPIO_SPEED_FREQ_VERY_HIGH);
142         mp_hal_pin_config(pin_B15, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, otg_alt);
143         mp_hal_pin_config_speed(pin_B15, GPIO_SPEED_FREQ_VERY_HIGH);
144 
145         #if defined(MICROPY_HW_USB_VBUS_DETECT_PIN)
146         // Configure VBUS Pin
147         mp_hal_pin_config(MICROPY_HW_USB_VBUS_DETECT_PIN, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0);
148         #endif
149 
150         #if defined(MICROPY_HW_USB_OTG_ID_PIN)
151         // Configure ID pin
152         mp_hal_pin_config(MICROPY_HW_USB_OTG_ID_PIN, MP_HAL_PIN_MODE_ALT_OPEN_DRAIN, MP_HAL_PIN_PULL_UP, otg_alt);
153         #endif
154 
155         // Enable calling WFI and correct function of the embedded USB_FS_IN_HS phy
156         __HAL_RCC_USB_OTG_HS_ULPI_CLK_SLEEP_DISABLE();
157         __HAL_RCC_USB_OTG_HS_CLK_SLEEP_ENABLE();
158 
159         // Enable USB HS Clocks
160 
161         #if defined(STM32F723xx) || defined(STM32F733xx)
162         // Needs to remain awake during sleep or else __WFI() will disable the USB
163         __HAL_RCC_USB_OTG_HS_ULPI_CLK_SLEEP_ENABLE();
164         __HAL_RCC_OTGPHYC_CLK_ENABLE();
165         __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE();
166         #endif
167 
168         __HAL_RCC_USB_OTG_HS_CLK_ENABLE();
169 
170         #else // !MICROPY_HW_USB_HS_IN_FS
171 
172         // Configure USB HS GPIOs
173         static const mp_hal_pin_obj_t usb_pins[] = {
174             pin_A5, pin_C0, MICROPY_HW_USB_HS_ULPI_NXT, MICROPY_HW_USB_HS_ULPI_DIR, // CLK, STP, NXT, DIR
175             pin_A3, pin_B0, pin_B1, pin_B5, pin_B10, pin_B11, pin_B12, pin_B13, // D0-D7
176         };
177         for (size_t i = 0; i < MP_ARRAY_SIZE(usb_pins); ++i) {
178             mp_hal_pin_config(usb_pins[i], MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, GPIO_AF10_OTG_HS);
179             mp_hal_pin_config_speed(usb_pins[i], GPIO_SPEED_FREQ_VERY_HIGH);
180         }
181 
182         // Enable USB HS Clocks
183         __HAL_RCC_USB_OTG_HS_CLK_ENABLE();
184         __HAL_RCC_USB_OTG_HS_CLK_SLEEP_ENABLE();
185         __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE();
186         __HAL_RCC_USB_OTG_HS_ULPI_CLK_SLEEP_ENABLE();
187 
188         #endif // !MICROPY_HW_USB_HS_IN_FS
189 
190         // Configure and enable USB HS interrupt
191         NVIC_SetPriority(OTG_HS_IRQn, IRQ_PRI_OTG_HS);
192         HAL_NVIC_EnableIRQ(OTG_HS_IRQn);
193     }
194     #endif // MICROPY_HW_USB_HS
195 }
196 
197 /**
198   * @brief  DeInitializes the PCD MSP.
199   * @param  hpcd: PCD handle
200   * @retval None
201   */
HAL_PCD_MspDeInit(PCD_HandleTypeDef * hpcd)202 void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd) {
203     #if !MICROPY_HW_USB_IS_MULTI_OTG
204     __HAL_RCC_USB_CLK_DISABLE();
205     #else
206 
207     if (hpcd->Instance == USB_OTG_FS) {
208         /* Disable USB FS Clocks */
209         __USB_OTG_FS_CLK_DISABLE();
210         __SYSCFG_CLK_DISABLE();
211     }
212     #if MICROPY_HW_USB_HS
213     else if (hpcd->Instance == USB_OTG_HS) {
214         /* Disable USB FS Clocks */
215         __USB_OTG_HS_CLK_DISABLE();
216         __SYSCFG_CLK_DISABLE();
217     }
218     #endif
219 
220     #endif
221 }
222 
223 /*******************************************************************************
224                        LL Driver Callbacks (PCD -> USB Device Library)
225 *******************************************************************************/
226 
227 /**
228   * @brief  Setup stage callback.
229   * @param  hpcd: PCD handle
230   * @retval None
231   */
HAL_PCD_SetupStageCallback(PCD_HandleTypeDef * hpcd)232 void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) {
233     USBD_LL_SetupStage(hpcd->pData, (uint8_t *)hpcd->Setup);
234 }
235 
236 /**
237   * @brief  Data Out stage callback.
238   * @param  hpcd: PCD handle
239   * @param  epnum: Endpoint Number
240   * @retval None
241   */
HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)242 void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) {
243     USBD_LL_DataOutStage(hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff);
244 }
245 
246 /**
247   * @brief  Data In stage callback.
248   * @param  hpcd: PCD handle
249   * @param  epnum: Endpoint Number
250   * @retval None
251   */
HAL_PCD_DataInStageCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)252 void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) {
253     USBD_LL_DataInStage(hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff);
254 }
255 
256 /**
257   * @brief  SOF callback.
258   * @param  hpcd: PCD handle
259   * @retval None
260   */
261 /*
262 This is now handled by the USB CDC interface.
263 void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
264 {
265   USBD_LL_SOF(hpcd->pData);
266 }
267 */
268 
269 /**
270   * @brief  Reset callback.
271   * @param  hpcd: PCD handle
272   * @retval None
273   */
HAL_PCD_ResetCallback(PCD_HandleTypeDef * hpcd)274 void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) {
275     USBD_SpeedTypeDef speed = USBD_SPEED_FULL;
276 
277     // Set USB Current Speed
278     switch (hpcd->Init.speed) {
279         #if defined(PCD_SPEED_HIGH)
280         case PCD_SPEED_HIGH:
281             speed = USBD_SPEED_HIGH;
282             break;
283         #endif
284 
285         case PCD_SPEED_FULL:
286             speed = USBD_SPEED_FULL;
287             break;
288 
289         default:
290             speed = USBD_SPEED_FULL;
291             break;
292     }
293     USBD_LL_SetSpeed(hpcd->pData, speed);
294 
295     // Reset Device
296     USBD_LL_Reset(hpcd->pData);
297 }
298 
299 /**
300   * @brief  Suspend callback.
301   * @param  hpcd: PCD handle
302   * @retval None
303   */
HAL_PCD_SuspendCallback(PCD_HandleTypeDef * hpcd)304 void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd) {
305     USBD_LL_Suspend(hpcd->pData);
306 }
307 
308 /**
309   * @brief  Resume callback.
310   * @param  hpcd: PCD handle
311   * @retval None
312   */
HAL_PCD_ResumeCallback(PCD_HandleTypeDef * hpcd)313 void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd) {
314     USBD_LL_Resume(hpcd->pData);
315 }
316 
317 /**
318   * @brief  ISOC Out Incomplete callback.
319   * @param  hpcd: PCD handle
320   * @param  epnum: Endpoint Number
321   * @retval None
322   */
HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)323 void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) {
324     USBD_LL_IsoOUTIncomplete(hpcd->pData, epnum);
325 }
326 
327 /**
328   * @brief  ISOC In Incomplete callback.
329   * @param  hpcd: PCD handle
330   * @param  epnum: Endpoint Number
331   * @retval None
332   */
HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)333 void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) {
334     USBD_LL_IsoINIncomplete(hpcd->pData, epnum);
335 }
336 
337 /**
338   * @brief  Connect callback.
339   * @param  hpcd: PCD handle
340   * @retval None
341   */
HAL_PCD_ConnectCallback(PCD_HandleTypeDef * hpcd)342 void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd) {
343     USBD_LL_DevConnected(hpcd->pData);
344 }
345 
346 /**
347   * @brief  Disconnect callback.
348   * @param  hpcd: PCD handle
349   * @retval None
350   */
HAL_PCD_DisconnectCallback(PCD_HandleTypeDef * hpcd)351 void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) {
352     USBD_LL_DevDisconnected(hpcd->pData);
353 }
354 
355 /*******************************************************************************
356                        LL Driver Interface (USB Device Library --> PCD)
357 *******************************************************************************/
358 
359 /**
360   * @brief  Initializes the Low Level portion of the Device driver.
361   * @param  pdev: Device handle
362   * @retval USBD Status
363   */
USBD_LL_Init(USBD_HandleTypeDef * pdev,int high_speed,const uint8_t * fifo_size)364 USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed, const uint8_t *fifo_size) {
365     #if MICROPY_HW_USB_FS
366     if (pdev->id == USB_PHY_FS_ID) {
367         #if defined(STM32WB)
368         PWR->CR2 |= PWR_CR2_USV; // USB supply is valid
369         #endif
370 
371         // Set LL Driver parameters
372         pcd_fs_handle.Instance = USB_OTG_FS;
373         #if MICROPY_HW_USB_CDC_NUM == 2
374         pcd_fs_handle.Init.dev_endpoints = 6;
375         #else
376         pcd_fs_handle.Init.dev_endpoints = 4;
377         #endif
378         pcd_fs_handle.Init.ep0_mps = 0x40;
379         pcd_fs_handle.Init.low_power_enable = 0;
380         pcd_fs_handle.Init.phy_itface = PCD_PHY_EMBEDDED;
381         pcd_fs_handle.Init.Sof_enable = 0;
382         pcd_fs_handle.Init.speed = PCD_SPEED_FULL;
383         #if defined(STM32L4)
384         pcd_fs_handle.Init.lpm_enable = DISABLE;
385         pcd_fs_handle.Init.battery_charging_enable = DISABLE;
386         #endif
387         #if MICROPY_HW_USB_IS_MULTI_OTG
388         pcd_fs_handle.Init.use_dedicated_ep1 = 0;
389         pcd_fs_handle.Init.dma_enable = 0;
390         #if !defined(MICROPY_HW_USB_VBUS_DETECT_PIN)
391         pcd_fs_handle.Init.vbus_sensing_enable = 0; // No VBUS Sensing on USB0
392         #else
393         pcd_fs_handle.Init.vbus_sensing_enable = 1;
394         #endif
395         #endif
396 
397         // Link The driver to the stack
398         pcd_fs_handle.pData = pdev;
399         pdev->pData = &pcd_fs_handle;
400 
401         // Initialize LL Driver
402         HAL_PCD_Init(&pcd_fs_handle);
403 
404         // Set FIFO buffer sizes
405         #if !MICROPY_HW_USB_IS_MULTI_OTG
406         uint32_t fifo_offset = USBD_PMA_RESERVE; // need to reserve some data at start of FIFO
407         for (size_t i = 0; i < USBD_PMA_NUM_FIFO; ++i) {
408             uint16_t ep_addr = ((i & 1) * 0x80) | (i >> 1);
409             HAL_PCDEx_PMAConfig(&pcd_fs_handle, ep_addr, PCD_SNG_BUF, fifo_offset);
410             fifo_offset += fifo_size[i] * 4;
411         }
412         #else
413         HAL_PCD_SetRxFiFo(&pcd_fs_handle, fifo_size[0] * 4);
414         for (size_t i = 0; i < USBD_FS_NUM_TX_FIFO; ++i) {
415             HAL_PCD_SetTxFiFo(&pcd_fs_handle, i, fifo_size[1 + i] * 4);
416         }
417         #endif
418     }
419     #endif
420     #if MICROPY_HW_USB_HS
421     if (pdev->id == USB_PHY_HS_ID) {
422         // Set LL Driver parameters
423         pcd_hs_handle.Instance = USB_OTG_HS;
424         #if MICROPY_HW_USB_CDC_NUM == 3
425         pcd_hs_handle.Init.dev_endpoints = 8;
426         #else
427         pcd_hs_handle.Init.dev_endpoints = 6;
428         #endif
429         pcd_hs_handle.Init.use_dedicated_ep1 = 0;
430         pcd_hs_handle.Init.ep0_mps = 0x40;
431         pcd_hs_handle.Init.dma_enable = 0;
432         pcd_hs_handle.Init.low_power_enable = 0;
433         pcd_hs_handle.Init.lpm_enable = DISABLE;
434         pcd_hs_handle.Init.battery_charging_enable = DISABLE;
435         pcd_hs_handle.Init.Sof_enable = 0;
436         pcd_hs_handle.Init.use_external_vbus = 0;
437 
438         #if !defined(MICROPY_HW_USB_VBUS_DETECT_PIN)
439         pcd_hs_handle.Init.vbus_sensing_enable = 0; // No VBUS Sensing on USB0
440         #else
441         pcd_hs_handle.Init.vbus_sensing_enable = 1;
442         #endif
443 
444         #if MICROPY_HW_USB_HS_IN_FS
445 
446         #if defined(STM32F723xx) || defined(STM32F733xx)
447         pcd_hs_handle.Init.phy_itface = USB_OTG_HS_EMBEDDED_PHY;
448         #else
449         pcd_hs_handle.Init.phy_itface = PCD_PHY_EMBEDDED;
450         #endif
451 
452         if (high_speed) {
453             pcd_hs_handle.Init.speed = PCD_SPEED_HIGH;
454         } else {
455             pcd_hs_handle.Init.speed = PCD_SPEED_HIGH_IN_FULL;
456         }
457 
458         #else
459 
460         // USB HS with external PHY
461         pcd_hs_handle.Init.phy_itface = PCD_PHY_ULPI;
462         pcd_hs_handle.Init.speed = PCD_SPEED_HIGH;
463 
464         #endif
465 
466         // Link The driver to the stack
467         pcd_hs_handle.pData = pdev;
468         pdev->pData = &pcd_hs_handle;
469 
470         // Initialize LL Driver
471         HAL_PCD_Init(&pcd_hs_handle);
472 
473         // Set FIFO buffer sizes
474         fifo_size += USBD_FS_NUM_FIFO; // skip over FS FIFO size values
475         HAL_PCD_SetRxFiFo(&pcd_hs_handle, fifo_size[0] * 4);
476         for (size_t i = 0; i < USBD_HS_NUM_TX_FIFO; ++i) {
477             HAL_PCD_SetTxFiFo(&pcd_hs_handle, i, fifo_size[1 + i] * 4);
478         }
479     }
480     #endif  // MICROPY_HW_USB_HS
481 
482     return USBD_OK;
483 }
484 
485 /**
486   * @brief  De-Initializes the Low Level portion of the Device driver.
487   * @param  pdev: Device handle
488   * @retval USBD Status
489   */
USBD_LL_DeInit(USBD_HandleTypeDef * pdev)490 USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev) {
491     HAL_PCD_DeInit(pdev->pData);
492     return USBD_OK;
493 }
494 
495 /**
496   * @brief  Starts the Low Level portion of the Device driver.
497   * @param  pdev: Device handle
498   * @retval USBD Status
499   */
USBD_LL_Start(USBD_HandleTypeDef * pdev)500 USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev) {
501     HAL_PCD_Start(pdev->pData);
502     return USBD_OK;
503 }
504 
505 /**
506   * @brief  Stops the Low Level portion of the Device driver.
507   * @param  pdev: Device handle
508   * @retval USBD Status
509   */
USBD_LL_Stop(USBD_HandleTypeDef * pdev)510 USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev) {
511     HAL_PCD_Stop(pdev->pData);
512     return USBD_OK;
513 }
514 
515 /**
516   * @brief  Opens an endpoint of the Low Level Driver.
517   * @param  pdev: Device handle
518   * @param  ep_addr: Endpoint Number
519   * @param  ep_type: Endpoint Type
520   * @param  ep_mps: Endpoint Max Packet Size
521   * @retval USBD Status
522   */
USBD_LL_OpenEP(USBD_HandleTypeDef * pdev,uint8_t ep_addr,uint8_t ep_type,uint16_t ep_mps)523 USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev,
524     uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps) {
525     HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type);
526     return USBD_OK;
527 }
528 
529 /**
530   * @brief  Closes an endpoint of the Low Level Driver.
531   * @param  pdev: Device handle
532   * @param  ep_addr: Endpoint Number
533   * @retval USBD Status
534   */
USBD_LL_CloseEP(USBD_HandleTypeDef * pdev,uint8_t ep_addr)535 USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) {
536     HAL_PCD_EP_Close(pdev->pData, ep_addr);
537     return USBD_OK;
538 }
539 
540 /**
541   * @brief  Flushes an endpoint of the Low Level Driver.
542   * @param  pdev: Device handle
543   * @param  ep_addr: Endpoint Number
544   * @retval USBD Status
545   */
USBD_LL_FlushEP(USBD_HandleTypeDef * pdev,uint8_t ep_addr)546 USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) {
547     HAL_PCD_EP_Flush(pdev->pData, ep_addr);
548     return USBD_OK;
549 }
550 
551 /**
552   * @brief  Sets a Stall condition on an endpoint of the Low Level Driver.
553   * @param  pdev: Device handle
554   * @param  ep_addr: Endpoint Number
555   * @retval USBD Status
556   */
USBD_LL_StallEP(USBD_HandleTypeDef * pdev,uint8_t ep_addr)557 USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) {
558     HAL_PCD_EP_SetStall(pdev->pData, ep_addr);
559     return USBD_OK;
560 }
561 
562 /**
563   * @brief  Clears a Stall condition on an endpoint of the Low Level Driver.
564   * @param  pdev: Device handle
565   * @param  ep_addr: Endpoint Number
566   * @retval USBD Status
567   */
USBD_LL_ClearStallEP(USBD_HandleTypeDef * pdev,uint8_t ep_addr)568 USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) {
569     HAL_PCD_EP_ClrStall(pdev->pData, ep_addr);
570     return USBD_OK;
571 }
572 
573 /**
574   * @brief  Returns Stall condition.
575   * @param  pdev: Device handle
576   * @param  ep_addr: Endpoint Number
577   * @retval Stall (1: yes, 0: No)
578   */
USBD_LL_IsStallEP(USBD_HandleTypeDef * pdev,uint8_t ep_addr)579 uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) {
580     PCD_HandleTypeDef *hpcd = pdev->pData;
581 
582     if ((ep_addr & 0x80) == 0x80) {
583         return hpcd->IN_ep[ep_addr & 0x7F].is_stall;
584     } else {
585         return hpcd->OUT_ep[ep_addr & 0x7F].is_stall;
586     }
587 }
588 
589 /**
590   * @brief  Assigns an USB address to the device
591   * @param  pdev: Device handle
592   * @param  dev_addr: USB address
593   * @retval USBD Status
594   */
USBD_LL_SetUSBAddress(USBD_HandleTypeDef * pdev,uint8_t dev_addr)595 USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr) {
596     HAL_PCD_SetAddress(pdev->pData, dev_addr);
597     return USBD_OK;
598 }
599 
600 /**
601   * @brief  Transmits data over an endpoint
602   * @param  pdev: Device handle
603   * @param  ep_addr: Endpoint Number
604   * @param  pbuf: Pointer to data to be sent
605   * @param  size: Data size
606   * @retval USBD Status
607   */
USBD_LL_Transmit(USBD_HandleTypeDef * pdev,uint8_t ep_addr,uint8_t * pbuf,uint16_t size)608 USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev,
609     uint8_t ep_addr, uint8_t *pbuf, uint16_t size) {
610     HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size);
611     return USBD_OK;
612 }
613 
614 /**
615   * @brief  Prepares an endpoint for reception
616   * @param  pdev: Device handle
617   * @param  ep_addr: Endpoint Number
618   * @param  pbuf:pointer to data to be received
619   * @param  size: data size
620   * @retval USBD Status
621   */
USBD_LL_PrepareReceive(USBD_HandleTypeDef * pdev,uint8_t ep_addr,uint8_t * pbuf,uint16_t size)622 USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev,
623     uint8_t ep_addr, uint8_t *pbuf, uint16_t size) {
624     HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size);
625     return USBD_OK;
626 }
627 
628 /**
629   * @brief  Returns the last transfered packet size.
630   * @param  pdev: Device handle
631   * @param  ep_addr: Endpoint Number
632   * @retval Recived Data Size
633   */
USBD_LL_GetRxDataSize(USBD_HandleTypeDef * pdev,uint8_t ep_addr)634 uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr) {
635     return HAL_PCD_EP_GetRxCount(pdev->pData, ep_addr);
636 }
637 
638 /**
639   * @brief  Delay routine for the USB Device Library
640   * @param  Delay: Delay in ms
641   * @retval None
642   */
USBD_LL_Delay(uint32_t Delay)643 void USBD_LL_Delay(uint32_t Delay) {
644     HAL_Delay(Delay);
645 }
646 
647 #endif // MICROPY_HW_USB_FS || MICROPY_HW_USB_HS
648 
649 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
650