Skip to content

Commit 90c0884

Browse files
authored
Merge pull request #3644 from bdolgov/fix/rp2040-hcd-set-report-pid
rp2040 host: fix SET_REPORT (and any OUT-data control xfer) sending DATA0 instead of DATA1
2 parents 7f146c9 + 72e0978 commit 90c0884

1 file changed

Lines changed: 9 additions & 3 deletions

File tree

src/portable/raspberrypi/rp2040/hcd_rp2040.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -617,10 +617,16 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b
617617
io_rw_32 *buf_reg = dpram_int_ep_buffer_ctrl(ep->interrupt_num);
618618
rp2usb_xfer_start(ep, ep_reg, buf_reg, buffer, NULL, buflen);
619619
} else {
620-
// Control endpoint can change direction 0x00 <-> 0x80 when changing stages
621-
if (ep_addr != ep->ep_addr) {
620+
// Control transfer data and status stages always start with DATA1, regardless of
621+
// whether the direction changed since the previous stage. SET_REPORT (and any other
622+
// host-to-device class request with an OUT data stage) keeps the same direction
623+
// across SETUP -> DATA, so we cannot key off "direction changed" -- we must reset
624+
// next_pid every time hcd_edpt_xfer is invoked on ep 0. Without this, the data stage
625+
// of SET_REPORT goes out as DATA0 because ep->next_pid is still 0 from hcd_edpt_open(),
626+
// which strict devices treat as a protocol violation and disconnect.
627+
if (tu_edpt_number(ep_addr) == 0) {
622628
ep->ep_addr = ep_addr;
623-
ep->next_pid = 1; // data and status stage start with DATA1
629+
ep->next_pid = 1;
624630
}
625631

626632
// If EPX is busy with another transfer, mark as pending

0 commit comments

Comments
 (0)