Skip to content

Commit bc14d3e

Browse files
committed
Fix hang on disconnect of non-compliant devices: Added timeout to RX path and buffer overflow check.
1 parent 528616d commit bc14d3e

File tree

1 file changed

+13
-2
lines changed

1 file changed

+13
-2
lines changed

src/pio_usb.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,18 +192,25 @@ int __no_inline_not_in_flash_func(pio_usb_bus_receive_packet_and_handshake)(
192192
// timing critical start
193193
if (t > 0) {
194194
if (handshake == USB_PID_ACK) {
195-
while ((pp->pio_usb_rx->irq & IRQ_RX_COMP_MASK) == 0) {
195+
uint32_t timeout = 240;
196+
while ((pp->pio_usb_rx->irq & IRQ_RX_COMP_MASK) == 0 && timeout--) {
196197
if (pio_sm_get_rx_fifo_level(pp->pio_usb_rx, pp->sm_rx)) {
197198
uint8_t data = pio_sm_get(pp->pio_usb_rx, pp->sm_rx) >> 24;
198199
crc_prev2 = crc_prev;
199200
crc_prev = crc;
200201
crc = update_usb_crc16(crc, data);
202+
if (idx > (sizeof(pp->usb_rx_buffer) / sizeof(pp->usb_rx_buffer[0]))) {
203+
return -1;
204+
}
201205
pp->usb_rx_buffer[idx++] = data;
202206
crc_receive = (crc_receive >> 8) | (data << 8);
203207
crc_receive_inverse = crc_receive ^ 0xffff;
204208
crc_match = (crc_receive_inverse == crc_prev2);
205209
}
206210
}
211+
if (timeout == 0) {
212+
return -1;
213+
}
207214

208215
if (idx >= 4 && crc_match) {
209216
pio_usb_bus_send_handshake(pp, USB_PID_ACK);
@@ -212,10 +219,14 @@ int __no_inline_not_in_flash_func(pio_usb_bus_receive_packet_and_handshake)(
212219
}
213220
} else {
214221
// just discard received data since we NAK/STALL anyway
215-
while ((pp->pio_usb_rx->irq & IRQ_RX_COMP_MASK) == 0) {
222+
uint32_t timeout = 240;
223+
while ((pp->pio_usb_rx->irq & IRQ_RX_COMP_MASK) == 0 && timeout--) {
216224
continue;
217225
}
218226
pio_sm_clear_fifos(pp->pio_usb_rx, pp->sm_rx);
227+
if (timeout == 0) {
228+
return -1;
229+
}
219230

220231
pio_usb_bus_send_handshake(pp, handshake);
221232
}

0 commit comments

Comments
 (0)