summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhathach <[email protected]>2026-01-16 13:39:06 +0700
committerhathach <[email protected]>2026-01-16 13:39:06 +0700
commit0c9a170dca9b0a0982b4b0462508ee4bda7a06da (patch)
tree0f3ede9d58dbe50ae823458db60a41b7e7c7ce07 /src
parent084ef43be65484c3fd928d1f224aed70b3d6af8a (diff)
implement hcd_device_close()
Diffstat (limited to 'src')
-rw-r--r--src/portable/raspberrypi/rp2040/hcd_rp2040.c121
1 files changed, 19 insertions, 102 deletions
diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c
index ff2db2499..8a891c49a 100644
--- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c
+++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c
@@ -252,12 +252,12 @@ static void hw_endpoint_init(hcd_endpoint_t *ep, uint8_t dev_addr, const tusb_de
const uint8_t transfer_type = ep_desc->bmAttributes.xfer;
// const uint8_t bmInterval = ep_desc->bInterval;
+ ep->hwep.wMaxPacketSize = wMaxPacketSize;
ep->hwep.ep_addr = ep_addr;
ep->dev_addr = dev_addr;
ep->transfer_type = transfer_type;
ep->need_pre = need_pre(dev_addr);
ep->hwep.next_pid = 0u;
- ep->hwep.wMaxPacketSize = wMaxPacketSize;
if (transfer_type != TUSB_XFER_INTERRUPT) {
ep->hwep.hw_data_buf = usbh_dpram->epx_data;
@@ -293,49 +293,8 @@ static void hw_endpoint_init(hcd_endpoint_t *ep, uint8_t dev_addr, const tusb_de
usb_hw->int_ep_addr_ctrl[int_idx] = addr_ctrl;
// Finally, activate interrupt endpoint
- usb_hw_set->int_ep_ctrl |= 1u << ep->interrupt_num;
- }
- #if 0
- pico_trace("hw_endpoint_init dev %d ep %02X xfer %d\n", ep->dev_addr, ep->hwep.ep_addr, transfer_type);
- pico_trace("dev %d ep %02X setup buffer @ 0x%p\n", ep->dev_addr, ep->hwep.ep_addr, ep->hwep.hw_data_buf);
- uint dpram_offset = hw_data_offset(ep->hwep.hw_data_buf);
- // Bits 0-5 should be 0
- assert(!(dpram_offset & 0b111111));
-
- // Fill in endpoint control register with buffer offset
- uint32_t ctrl_value = EP_CTRL_ENABLE_BITS | EP_CTRL_INTERRUPT_PER_BUFFER |
- ((uint32_t)transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset;
- if (bmInterval) {
- ctrl_value |= (uint32_t)((bmInterval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB);
- }
-
- io_rw_32 *ctrl_reg = hwep_ctrl_reg_host(ep);
- *ctrl_reg = ctrl_value;
- pico_trace("endpoint control (0x%p) <- 0x%lx\n", ctrl_reg, ctrl_value);
-
- if (ep != &epx) {
- // Endpoint has its own addr_endp and interrupt bits to be setup!
- // This is an interrupt/async endpoint. so need to set up ADDR_ENDP register with:
- // - device address
- // - endpoint number / direction
- // - preamble
- uint32_t reg = (uint32_t)(dev_addr | (num << USB_ADDR_ENDP1_ENDPOINT_LSB));
-
- if (dir == TUSB_DIR_OUT) {
- reg |= USB_ADDR_ENDP1_INTEP_DIR_BITS;
- }
-
- if (need_pre(dev_addr)) {
- reg |= USB_ADDR_ENDP1_INTEP_PREAMBLE_BITS;
- }
- usb_hw->int_ep_addr_ctrl[ep->interrupt_num] = reg;
-
- // Finally, enable interrupt that endpoint
- usb_hw_set->int_ep_ctrl = 1 << (ep->interrupt_num + 1);
-
- // If it's an interrupt endpoint we need to set up the buffer control register
+ usb_hw_set->int_ep_ctrl = 1u << ep->interrupt_num;
}
- #endif
}
//--------------------------------------------------------------------+
@@ -414,33 +373,29 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) {
(void)rhport;
(void)dev_addr;
- #if 0
// reset epx if it is currently active with unplugged device
- if (epx.hw_ep.wMaxPacketSize > 0 && epx.hw_ep.active && epx.dev_addr == dev_addr) {
- epx.hw_ep.wMaxPacketSize = 0;
- *hwep_ctrl_reg_host(&epx) = 0;
- *hwbuf_ctrl_reg_host(&epx) = 0;
- hw_endpoint_reset_transfer(&epx.hw_ep);
+ if (epx->hwep.wMaxPacketSize > 0 && epx->dev_addr == dev_addr) {
+ // if (epx->hwep.active) {
+ // // need to abort transfer
+ // }
+ epx->hwep.wMaxPacketSize = 0;
}
- // dev0 only has ep0
- if (dev_addr != 0) {
- for (size_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++) {
- hcd_endpoint_t *ep = &ep_pool[i];
- if (ep->dev_addr == dev_addr && ep->hwep.wMaxPacketSize > 0) {
- // in case it is an interrupt endpoint, disable it
- usb_hw_clear->int_ep_ctrl = (1 << (ep->interrupt_num + 1));
- usb_hw->int_ep_addr_ctrl[ep->interrupt_num] = 0;
+ for (size_t i = 0; i < TU_ARRAY_SIZE(ep_pool); i++) {
+ hcd_endpoint_t *ep = &ep_pool[i];
+ if (ep->dev_addr == dev_addr && ep->hwep.wMaxPacketSize > 0) {
+ if (ep->interrupt_num) {
+ // disable interrupt endpoint
+ usb_hw_clear->int_ep_ctrl = 1u << ep->interrupt_num;
+ usb_hw->int_ep_addr_ctrl[ep->interrupt_num - 1] = 0;
- // unconfigure the endpoint
- ep->hwep.wMaxPacketSize = 0;
- *hwep_ctrl_reg_host(ep) = 0;
- *hwbuf_ctrl_reg_host(ep) = 0;
- hw_endpoint_reset_transfer(&ep->hwep);
+ usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num - 1].ctrl = 0;
+ usbh_dpram->int_ep_ctrl[ep->interrupt_num - 1].ctrl = 0;
}
+
+ ep->hwep.wMaxPacketSize = 0; // mark as unused
}
}
- #endif
}
uint32_t hcd_frame_number(uint8_t rhport) {
@@ -491,7 +446,7 @@ TU_ATTR_ALWAYS_INLINE static inline void sie_start_xfer(uint32_t value) {
}
// xfer using epx
-static bool edpt_xfer(hcd_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len) {
+static void edpt_xfer(hcd_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16_t total_len) {
if (ep->transfer_type == TUSB_XFER_INTERRUPT) {
// For interrupt endpoint control and buffer is already configured
// Note: Interrupt is single buffered only
@@ -522,8 +477,6 @@ static bool edpt_xfer(hcd_endpoint_t *ep, uint8_t *buffer, tu_fifo_t *ff, uint16
(ep->need_pre ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0);
sie_start_xfer(sie_ctrl);
}
-
- return true;
}
bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) {
@@ -540,42 +493,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b
edpt_xfer(ep, buffer, NULL, buflen);
- #if 0
- // EP should be inactive
- // assert(!ep->active);
-
- // Control endpoint can change direction 0x00 <-> 0x80
- if (ep_addr != ep->ep_addr) {
- assert(ep_num == 0);
-
- // Direction has flipped on endpoint control so re init it but with same properties
- hw_endpoint_init(ep, dev_addr, ep_addr, ep->wMaxPacketSize, TUSB_XFER_CONTROL, 0);
- }
-
- // If a normal transfer (non-interrupt) then initiate using
- // sie ctrl registers. Otherwise, interrupt ep registers should
- // already be configured
- if (ep == &epx) {
- hw_endpoint_xfer_start(ep, buffer, NULL, buflen);
-
- // That has set up buffer control, endpoint control etc
- // for host we have to initiate the transfer
- usb_hw->dev_addr_ctrl = (uint32_t) (dev_addr | (ep_num << USB_ADDR_ENDP_ENDPOINT_LSB));
-
- uint32_t flags = USB_SIE_CTRL_START_TRANS_BITS | SIE_CTRL_BASE |
- (ep_dir ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS) |
- (need_pre(dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0);
- // START_TRANS bit on SIE_CTRL seems to exhibit the same behavior as the AVAILABLE bit
- // described in RP2040 Datasheet, release 2.1, section "4.1.2.5.1. Concurrent access".
- // We write everything except the START_TRANS bit first, then wait some cycles.
- usb_hw->sie_ctrl = flags & ~USB_SIE_CTRL_START_TRANS_BITS;
- busy_wait_at_least_cycles(12);
- usb_hw->sie_ctrl = flags;
- } else {
- hw_endpoint_xfer_start(ep, buffer, NULL, buflen);
- }
- #endif
-
return true;
}