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
1717#include <usbd_pybricks.h>
1818
1919#include <pbdrv/usb.h>
20+ #include <pbio/protocol.h>
2021#include <pbio/util.h>
2122#include <pbsys/command.h>
2223#include <pbsys/status.h>
@@ -29,7 +30,10 @@ PROCESS(pbdrv_usb_process, "USB");
2930// These buffers need to be 32-bit aligned because the USB driver moves data
3031// to/from FIFOs in 32-bit chunks.
3132static uint8_t usb_in_buf [USBD_PYBRICKS_MAX_PACKET_SIZE ] __aligned (4 );
33+ static uint8_t usb_response_buf [1 + sizeof (uint32_t )] __aligned (4 );
3234static volatile uint32_t usb_in_sz ;
35+ static volatile uint32_t usb_response_sz ;
36+ static volatile bool transmitting ;
3337
3438static USBD_HandleTypeDef husbd ;
3539static PCD_HandleTypeDef hpcd ;
@@ -140,6 +144,8 @@ void pbdrv_usb_stm32_handle_vbus_irq(bool active) {
140144static USBD_StatusTypeDef Pybricks_Itf_Init (void ) {
141145 USBD_Pybricks_SetRxBuffer (& husbd , usb_in_buf );
142146 usb_in_sz = 0 ;
147+ usb_response_sz = 0 ;
148+ transmitting = false;
143149
144150 return USBD_OK ;
145151}
@@ -182,8 +188,17 @@ static USBD_StatusTypeDef Pybricks_Itf_Receive(uint8_t *Buf, uint32_t Len) {
182188 * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
183189 */
184190static USBD_StatusTypeDef Pybricks_Itf_TransmitCplt (uint8_t * Buf , uint32_t Len , uint8_t epnum ) {
191+ USBD_StatusTypeDef ret = USBD_OK ;
192+
193+ if (Buf == usb_response_buf ) {
194+ usb_response_sz = 0 ;
195+ } else {
196+ ret = USBD_FAIL ;
197+ }
198+
199+ transmitting = false;
185200 process_poll (& pbdrv_usb_process );
186- return USBD_OK ;
201+ return ret ;
187202}
188203
189204static USBD_Pybricks_ItfTypeDef USBD_Pybricks_fops = {
@@ -224,6 +239,7 @@ PROCESS_THREAD(pbdrv_usb_process, ev, data) {
224239 static PBIO_ONESHOT (bcd_oneshot );
225240 static PBIO_ONESHOT (pwrdn_oneshot );
226241 static bool bcd_busy ;
242+ static pbio_pybricks_error_t result ;
227243
228244 PROCESS_POLLHANDLER ({
229245 if (!bcd_busy && pbio_oneshot (!vbus_active , & no_vbus_oneshot )) {
@@ -268,14 +284,28 @@ PROCESS_THREAD(pbdrv_usb_process, ev, data) {
268284 if (usb_in_sz ) {
269285 switch (usb_in_buf [0 ]) {
270286 case USBD_PYBRICKS_OUT_EP_MSG_COMMAND :
271- pbsys_command (usb_in_buf + 1 , usb_in_sz - 1 );
287+ if (usb_response_sz == 0 ) {
288+ result = pbsys_command (usb_in_buf + 1 , usb_in_sz - 1 );
289+ usb_response_buf [0 ] = USBD_PYBRICKS_IN_EP_MSG_RESPONSE ;
290+ pbio_set_uint32_le (& usb_response_buf [1 ], result );
291+ usb_response_sz = sizeof (usb_response_buf );
292+ }
272293 break ;
273294 }
274295
275296 // Prepare to receive the next packet
276297 usb_in_sz = 0 ;
277298 USBD_Pybricks_ReceivePacket (& husbd );
278299 }
300+
301+ if (transmitting ) {
302+ continue ;
303+ }
304+
305+ if (usb_response_sz ) {
306+ transmitting = true;
307+ USBD_Pybricks_TransmitPacket (& husbd , usb_response_buf , usb_response_sz );
308+ }
279309 }
280310
281311 PROCESS_END ();
0 commit comments