PM5: bound usb_write()'s tx-complete wait

The two g_tx_completed spin loops in usb_write() had no timeout at all -
if the host ever stopped pulling an IN packet while the device still read
as enumerated, PM5 would spin forever with no recovery path. Add a
spin-iteration bound (not tick-based: g_tx_completed is set from the USB
core's own ISR, and the shared ticks timer is routinely stopped by LF/HF
code at arbitrary points), matching the existing bounded-wait pattern
used elsewhere in this codebase.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Tom HarknessandClaude Sonnet 5 authored and Philippe Teuwen committed 2026-10-04 14:24:10 +02:00
1 parent 63063bd030
commit 2e2720a1da
1 file changed
+15
+15
View File
@@ -18,6 +18,13 @@ static otg_core_type otg_core_struct;
static usbd_core_type *udev = &(otg_core_struct.dev);
static usbd_desc_t vp_desc;
// Spin-wait iteration bound for usb_write()'s tx-complete wait, not a time
// unit - g_tx_completed is set from the USB core's own IN-endpoint ISR, so
// this can't use the shared ticks timer (see ticks_apis.h StartTicks()/
// StopTicks() callers elsewhere in armsrc - it's routinely stopped by
// LF/HF code at the exact moments a reply may need to go out).
#define USB_TX_COMPLETE_TIMEOUT 2000000
/**
* @brief get device descriptor
* @retval usbd_desc
@@ -515,10 +522,14 @@ int usb_write(const uint8_t *data, const size_t len) {
// wait for send complete
cdc_struct_type *pcdc = (cdc_struct_type *)(udev->class_handler->pdata);
uint32_t tx_timeout = 0;
while (pcdc->g_tx_completed != 1) {
if (usb_check() == false) {
return PM3_EIO;
}
if (tx_timeout++ > USB_TX_COMPLETE_TIMEOUT) {
return PM3_EIO;
}
// working for send to HOST...
// Have a cup of tea?
}
@@ -531,10 +542,14 @@ int usb_write(const uint8_t *data, const size_t len) {
if (usb_vcp_send_data(udev, (uint8_t *) data, 0) != SUCCESS) {
return PM3_EIO;
}
tx_timeout = 0;
while (pcdc->g_tx_completed != 1) {
if (usb_check() == false) {
return PM3_EIO;
}
if (tx_timeout++ > USB_TX_COMPLETE_TIMEOUT) {
return PM3_EIO;
}
}
}