Skip to content

Commit

Permalink
Fix hang on disconnect of non-compliant devices: Added timeout to RX …
Browse files Browse the repository at this point in the history
…path and buffer overflow check.
  • Loading branch information
wiredopposite committed Dec 14, 2024
1 parent 528616d commit bc14d3e
Showing 1 changed file with 13 additions and 2 deletions.
15 changes: 13 additions & 2 deletions src/pio_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,18 +192,25 @@ int __no_inline_not_in_flash_func(pio_usb_bus_receive_packet_and_handshake)(
// timing critical start
if (t > 0) {
if (handshake == USB_PID_ACK) {
while ((pp->pio_usb_rx->irq & IRQ_RX_COMP_MASK) == 0) {
uint32_t timeout = 240;
while ((pp->pio_usb_rx->irq & IRQ_RX_COMP_MASK) == 0 && timeout--) {
if (pio_sm_get_rx_fifo_level(pp->pio_usb_rx, pp->sm_rx)) {
uint8_t data = pio_sm_get(pp->pio_usb_rx, pp->sm_rx) >> 24;
crc_prev2 = crc_prev;
crc_prev = crc;
crc = update_usb_crc16(crc, data);
if (idx > (sizeof(pp->usb_rx_buffer) / sizeof(pp->usb_rx_buffer[0]))) {
return -1;
}
pp->usb_rx_buffer[idx++] = data;
crc_receive = (crc_receive >> 8) | (data << 8);
crc_receive_inverse = crc_receive ^ 0xffff;
crc_match = (crc_receive_inverse == crc_prev2);
}
}
if (timeout == 0) {
return -1;
}

if (idx >= 4 && crc_match) {
pio_usb_bus_send_handshake(pp, USB_PID_ACK);
Expand All @@ -212,10 +219,14 @@ int __no_inline_not_in_flash_func(pio_usb_bus_receive_packet_and_handshake)(
}
} else {
// just discard received data since we NAK/STALL anyway
while ((pp->pio_usb_rx->irq & IRQ_RX_COMP_MASK) == 0) {
uint32_t timeout = 240;
while ((pp->pio_usb_rx->irq & IRQ_RX_COMP_MASK) == 0 && timeout--) {
continue;
}
pio_sm_clear_fifos(pp->pio_usb_rx, pp->sm_rx);
if (timeout == 0) {
return -1;
}

pio_usb_bus_send_handshake(pp, handshake);
}
Expand Down

0 comments on commit bc14d3e

Please sign in to comment.