11// SPDX-License-Identifier: MIT
2- // Copyright (c) 2022 The Pybricks Authors
2+ // Copyright (c) 2022-2025 The Pybricks Authors
33
44// Main file for STM32F4 USB driver.
55
1818#include <usbd_pybricks.h>
1919
2020#include <pbdrv/usb.h>
21+ #include <pbio/protocol.h>
2122#include <pbio/util.h>
2223#include <pbsys/command.h>
2324#include <pbsys/status.h>
@@ -30,7 +31,10 @@ PROCESS(pbdrv_usb_process, "USB");
3031// These buffers need to be 32-bit aligned because the USB driver moves data
3132// to/from FIFOs in 32-bit chunks.
3233static uint8_t usb_in_buf [USBD_PYBRICKS_MAX_PACKET_SIZE ] __aligned (4 );
34+ static uint8_t usb_response_buf [1 + sizeof (uint32_t )] __aligned (4 ) __aligned (4 );
3335static volatile uint32_t usb_in_sz ;
36+ static volatile uint32_t usb_response_sz ;
37+ static volatile bool transmitting ;
3438
3539static USBD_HandleTypeDef husbd ;
3640static PCD_HandleTypeDef hpcd ;
@@ -141,6 +145,8 @@ void pbdrv_usb_stm32_handle_vbus_irq(bool active) {
141145static USBD_StatusTypeDef Pybricks_Itf_Init (void ) {
142146 USBD_Pybricks_SetRxBuffer (& husbd , usb_in_buf );
143147 usb_in_sz = 0 ;
148+ usb_response_sz = 0 ;
149+ transmitting = false;
144150
145151 return USBD_OK ;
146152}
@@ -183,8 +189,17 @@ static USBD_StatusTypeDef Pybricks_Itf_Receive(uint8_t *Buf, uint32_t Len) {
183189 * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
184190 */
185191static USBD_StatusTypeDef Pybricks_Itf_TransmitCplt (uint8_t * Buf , uint32_t Len , uint8_t epnum ) {
192+ USBD_StatusTypeDef ret = USBD_OK ;
193+
194+ if (Buf == usb_response_buf ) {
195+ usb_response_sz = 0 ;
196+ } else {
197+ ret = USBD_FAIL ;
198+ }
199+
200+ transmitting = false;
186201 process_poll (& pbdrv_usb_process );
187- return USBD_OK ;
202+ return ret ;
188203}
189204
190205static USBD_Pybricks_ItfTypeDef USBD_Pybricks_fops = {
@@ -225,6 +240,7 @@ PROCESS_THREAD(pbdrv_usb_process, ev, data) {
225240 static PBIO_ONESHOT (bcd_oneshot );
226241 static PBIO_ONESHOT (pwrdn_oneshot );
227242 static bool bcd_busy ;
243+ static pbio_pybricks_error_t result ;
228244
229245 PROCESS_POLLHANDLER ({
230246 if (!bcd_busy && pbio_oneshot (!vbus_active , & no_vbus_oneshot )) {
@@ -269,14 +285,28 @@ PROCESS_THREAD(pbdrv_usb_process, ev, data) {
269285 if (usb_in_sz ) {
270286 switch (usb_in_buf [0 ]) {
271287 case USBD_PYBRICKS_OUT_EP_MSG_COMMAND :
272- pbsys_command (usb_in_buf + 1 , usb_in_sz - 1 );
288+ if (usb_response_sz == 0 ) {
289+ result = pbsys_command (usb_in_buf + 1 , usb_in_sz - 1 );
290+ usb_response_buf [0 ] = USBD_PYBRICKS_IN_EP_MSG_RESPONSE ;
291+ pbio_set_uint32_le (& usb_response_buf [1 ], result );
292+ usb_response_sz = sizeof (usb_response_buf );
293+ }
273294 break ;
274295 }
275296
276297 // Prepare to receive the next packet
277298 usb_in_sz = 0 ;
278299 USBD_Pybricks_ReceivePacket (& husbd );
279300 }
301+
302+ if (transmitting ) {
303+ continue ;
304+ }
305+
306+ if (usb_response_sz ) {
307+ transmitting = true;
308+ USBD_Pybricks_TransmitPacket (& husbd , usb_response_buf , usb_response_sz );
309+ }
280310 }
281311
282312 PROCESS_END ();
0 commit comments