Merge branch 'xfer_close' into testing

This commit is contained in:
HiFiPhile 2025-06-22 17:21:46 +02:00
commit fa5856c72a

View File

@ -96,6 +96,7 @@ typedef struct {
uint8_t err_count : 3;
uint8_t period_split_nyet_count : 3;
uint8_t halted_nyet : 1;
uint8_t closing : 1; // closing channel
};
uint8_t result;
@ -456,11 +457,23 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport) {
// HCD closes all opened endpoints belong to this device
void hcd_device_close(uint8_t rhport, uint8_t dev_addr) {
(void) rhport;
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
for (uint8_t i = 0; i < (uint8_t) CFG_TUH_DWC2_ENDPOINT_MAX; i++) {
hcd_endpoint_t* edpt = &_hcd_data.edpt[i];
if (edpt->hcchar_bm.enable && edpt->hcchar_bm.dev_addr == dev_addr) {
tu_memclr(edpt, sizeof(hcd_endpoint_t));
for (uint8_t ch_id = 0; ch_id < (uint8_t) DWC2_CHANNEL_COUNT_MAX; ch_id++) {
hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id];
if (xfer->allocated && xfer->ep_id == i) {
dwc2_channel_t* channel = &dwc2->channel[ch_id];
dwc2_channel_split_t hcsplt = {.value = channel->hcsplt};
xfer->closing = 1;
// Channel disable must not be programmed for non-split periodic channels
if (!channel_is_periodic(channel->hcchar) || hcsplt.split_en) {
channel_disable(dwc2, channel);
}
}
}
}
}
}
@ -946,6 +959,11 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h
} else if (xfer->err_count == HCD_XFER_ERROR_MAX) {
xfer->result = XFER_RESULT_FAILED;
is_done = true;
} else if (xfer->closing) {
// channel is closing, de-allocate channel
channel_dealloc(dwc2, ch_id);
// don't send event
is_done = false;
} else {
// got here due to NAK or NYET
channel_xfer_in_retry(dwc2, ch_id, hcint);
@ -1006,6 +1024,11 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t
} else if (xfer->err_count == HCD_XFER_ERROR_MAX) {
xfer->result = XFER_RESULT_FAILED;
is_done = true;
} else if (xfer->closing) {
// channel is closing, de-allocate channel
channel_dealloc(dwc2, ch_id);
// don't send event
is_done = false;
} else {
// Got here due to NAK or NYET
TU_ASSERT(channel_xfer_start(dwc2, ch_id));
@ -1122,6 +1145,13 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci
// retry start-split in next binterval
channel_xfer_in_retry(dwc2, ch_id, hcint);
}
if (xfer->closing) {
// channel is closing, de-allocate channel
channel_dealloc(dwc2, ch_id);
// don't send event
is_done = false;
}
}
return is_done;
@ -1183,6 +1213,13 @@ static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hc
channel->hcchar |= HCCHAR_CHENA;
}
}
if (xfer->closing) {
// channel is closing, de-allocate channel
channel_dealloc(dwc2, ch_id);
// don't send event
is_done = false;
}
} else if (hcint & HCINT_ACK) {
xfer->err_count = 0;
channel->hcintmsk &= ~HCINT_ACK;