110#if CFG_TUD_ENABLED && defined(TUP_USBIP_FSDEV) && \
111 !(defined(TUP_USBIP_FSDEV_CH32) && CFG_TUD_WCH_USBIP_FSDEV == 0)
115#if defined(TUP_USBIP_FSDEV_STM32)
117#elif defined(TUP_USBIP_FSDEV_CH32)
120 #error "Unknown USB IP"
135 uint16_t max_packet_size;
163static uint8_t
dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type);
190 for (
volatile uint32_t i = 0; i < 200; i++) {
195 FSDEV_REG->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN;
196 for (
volatile uint32_t i = 0; i < 200; i++) {
200 FSDEV_REG->CNTR &= ~USB_CNTR_PDWN;
203 for (
volatile uint32_t i = 0; i < 200; i++) {
208#if !defined(FSDEV_BUS_32BIT)
210 FSDEV_REG->BTABLE = FSDEV_BTABLE_BASE;
216 for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) {
221 FSDEV_REG->CNTR |= USB_CNTR_RESETM | USB_CNTR_ESOFM | USB_CNTR_CTRM |
222 USB_CNTR_SUSPM | USB_CNTR_WKUPM | USB_CNTR_PMAOVRM;
235 FSDEV_REG->CNTR |= USB_CNTR_SOFM;
237 FSDEV_REG->CNTR &= ~USB_CNTR_SOFM;
255 FSDEV_REG->CNTR |= USB_CNTR_RESUME;
260 FSDEV_REG->DADDR = 0u;
262 for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) {
271 ep_buf_ptr = FSDEV_BTABLE_BASE + 8 * FSDEV_EP_COUNT;
275 FSDEV_REG->DADDR = USB_DADDR_EF;
280 uint32_t ep_reg =
ep_read(ep_id) | USB_EP_CTR_TX | USB_EP_CTR_RX;
282 uint8_t
const ep_num = ep_reg & USB_EPADDR_FIELD;
289 if (!
xfer->iso_in_sending) {
292 xfer->iso_in_sending =
false;
293 uint8_t buf_id = (ep_reg & USB_EP_DTOG_TX) ? 0 : 1;
327 uint32_t ep_reg =
ep_read(ep_id) | USB_EP_CTR_TX | USB_EP_CTR_RX;
328 uint8_t
const ep_num = ep_reg & USB_EPADDR_FIELD;
334 buf_id = (ep_reg & USB_EP_DTOG_RX) ? 0 : 1;
346 xfer->queued_len += rx_count;
348 if ((rx_count < xfer->max_packet_size) || (
xfer->queued_len >=
xfer->
total_len)) {
372 uint32_t int_status = FSDEV_REG->ISTR;
375 if (int_status & USB_ISTR_SOF) {
380 if (int_status & USB_ISTR_RESET) {
388 if (int_status & USB_ISTR_WKUP) {
389 FSDEV_REG->CNTR &= ~USB_CNTR_LPMODE;
390 FSDEV_REG->CNTR &= ~USB_CNTR_FSUSP;
396 if (int_status & USB_ISTR_SUSP) {
401 FSDEV_REG->CNTR |= USB_CNTR_FSUSP;
402 FSDEV_REG->CNTR |= USB_CNTR_LPMODE;
409 if (int_status & USB_ISTR_ESOF) {
411 FSDEV_REG->CNTR &= ~USB_CNTR_RESUME;
420 while (FSDEV_REG->ISTR & USB_ISTR_CTR) {
422 uint32_t
const ep_id = FSDEV_REG->ISTR & USB_ISTR_EP_ID;
423 uint32_t
const ep_reg =
ep_read(ep_id);
425 if (ep_reg & USB_EP_CTR_RX) {
426 #ifdef FSDEV_BUS_32BIT
442 volatile uint32_t cycle_count = 20;
443 while (cycle_count > 0U) {
448 if (ep_reg & USB_EP_SETUP) {
456 if (ep_reg & USB_EP_CTR_TX) {
462 if (int_status & USB_ISTR_PMAOVR) {
481 FSDEV_REG->DADDR = (USB_DADDR_EF |
dev_addr);
494 uint8_t blsize, num_block;
508 TU_ASSERT(
ep_buf_ptr <= FSDEV_PMA_SIZE, 0xFFFF);
521 for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) {
563 uint16_t pma_addr0 =
dcd_pma_alloc(CFG_TUD_ENDPOINT0_SIZE,
false);
564 uint16_t pma_addr1 =
dcd_pma_alloc(CFG_TUD_ENDPOINT0_SIZE,
false);
569 uint32_t ep_reg =
ep_read(0) & ~USB_EPREG_MASK;
570 ep_reg |= USB_EP_CONTROL;
586 TU_ASSERT(ep_idx < FSDEV_EP_COUNT);
588 uint32_t ep_reg =
ep_read(ep_idx) & ~USB_EPREG_MASK;
589 ep_reg |=
tu_edpt_number(ep_addr) | USB_EP_CTR_TX | USB_EP_CTR_RX;
594 ep_reg |= USB_EP_BULK;
597 ep_reg |= USB_EP_INTERRUPT;
610 xfer->max_packet_size = packet_size;
611 xfer->ep_idx = ep_idx;
618 ep_reg &= ~(USB_EPRX_STAT | USB_EP_DTOG_RX);
620 ep_reg &= ~(USB_EPTX_STAT | USB_EP_DTOG_TX);
631 for (uint32_t i = 1; i < FSDEV_EP_COUNT; i++) {
644 ep_buf_ptr = FSDEV_BTABLE_BASE + 8 * CFG_TUD_ENDPPOINT_MAX + 2 * CFG_TUD_ENDPOINT0_SIZE;
656#if FSDEV_PMA_SIZE > 1024u
657 uint32_t pma_addr =
dcd_pma_alloc(largest_packet_size,
true);
658 uint16_t pma_addr2 = pma_addr >> 16;
660 uint32_t pma_addr =
dcd_pma_alloc(largest_packet_size,
false);
661 uint16_t pma_addr2 = pma_addr;
668 xfer->ep_idx = ep_idx;
680 uint8_t
const ep_idx =
xfer->ep_idx;
684 uint32_t ep_reg =
ep_read(ep_idx) & ~USB_EPREG_MASK;
685 ep_reg |=
tu_edpt_number(ep_addr) | USB_EP_ISOCHRONOUS | USB_EP_CTR_TX | USB_EP_CTR_RX;
699 uint32_t ep_reg =
ep_read(ep_ix) | USB_EP_CTR_TX | USB_EP_CTR_RX;
705 buf_id = (ep_reg & USB_EP_DTOG_TX) ? 1 : 0;
716 xfer->queued_len += len;
722 xfer->iso_in_sending =
true;
724 ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(
TUSB_DIR_IN);
732 uint8_t
const ep_idx =
xfer->ep_idx;
737 uint32_t ep_reg =
ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX;
738 ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir);
764 xfer->queued_len = 0;
777 xfer->queued_len = 0;
787 uint8_t
const ep_idx =
xfer->ep_idx;
789 uint32_t ep_reg =
ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX;
790 ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir);
802 uint8_t
const ep_idx =
xfer->ep_idx;
804 uint32_t ep_reg =
ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX;
805 ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir) | EP_DTOG_MASK(dir);
822 if (nbytes == 0)
return true;
826 const uint8_t *src8 = src;
829 pma_buf->
value = fsdevbus_unaligned_read(src8);
838 for(uint16_t i = 0; i < odd; i++) {
839 temp |= *src8++ << (i * 8);
851 if (nbytes == 0)
return true;
855 uint8_t *dst8 = (uint8_t *)dst;
868 *dst8++ = (uint8_t) (
temp & 0xfful);
878 if (wNBytes == 0)
return true;
885 uint16_t cnt_wrap =
tu_min16(wNBytes - cnt_lin,
info.len_wrap);
886 uint16_t
const cnt_total = cnt_lin + cnt_wrap;
892 uint8_t
const *src8 = (uint8_t
const*)
info.ptr_lin;
900 src8 = (uint8_t
const*)
info.ptr_wrap;
905 for(i = 0; i < lin_odd; i++) {
906 temp |= *src8++ << (i * 8);
909 src8 = (uint8_t
const*)
info.ptr_wrap;
910 for(; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) {
911 temp |= *src8++ << (i * 8);
927 if (wNBytes == 0)
return true;
935 uint16_t cnt_wrap =
tu_min16(wNBytes - cnt_lin,
info.len_wrap);
936 uint16_t cnt_total = cnt_lin + cnt_wrap;
943 uint8_t *dst8 = (uint8_t *)
info.ptr_lin;
951 dst8 = (uint8_t *)
info.ptr_wrap;
959 for (i = 0; i < lin_odd; i++) {
960 *dst8++ = (uint8_t) (
temp & 0xfful);
964 dst8 = (uint8_t *)
info.ptr_wrap;
965 for (; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) {
966 *dst8++ = (uint8_t) (
temp & 0xfful);
static TU_ATTR_ALWAYS_INLINE void dcd_event_bus_signal(uint8_t rhport, dcd_eventid_t eid, bool in_isr)
static TU_ATTR_ALWAYS_INLINE void dcd_event_xfer_complete(uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr)
static TU_ATTR_ALWAYS_INLINE void dcd_event_sof(uint8_t rhport, uint32_t frame_count, bool in_isr)
static TU_ATTR_ALWAYS_INLINE void dcd_event_setup_received(uint8_t rhport, uint8_t const *setup, bool in_isr)
void dcd_int_disable(uint8_t rhport)
void dcd_connect(uint8_t rhport)
static TU_ATTR_ALWAYS_INLINE void dcd_event_bus_reset(uint8_t rhport, tusb_speed_t speed, bool in_isr)
struct TU_ATTR_ALIGNED(4)
void dcd_int_enable(uint8_t rhport)
static TU_ATTR_ALWAYS_INLINE bool ep_is_iso(ep_cmd_sts_t *ep_cs, bool is_highspeed)
xfer_td_t xfer[EP_CBI_COUNT+1][2]
static ep_reg_t ep_read(uint8_t rhport, uint8_t ep_num)
static void ep_write(uint8_t rhport, uint8_t ep_num, ep_reg_t val)
static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes)
bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep)
static xfer_ctl_t xfer_status[CFG_TUD_ENDPPOINT_MAX][2]
bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes)
static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir)
static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes)
static uint8_t remoteWakeCountdown
static TU_ATTR_ALWAYS_INLINE void edpt0_prepare_setup(void)
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes)
void dcd_int_handler(uint8_t rhport)
static TU_ATTR_ALWAYS_INLINE xfer_ctl_t * xfer_ctl_ptr(uint8_t epnum, uint8_t dir)
void dcd_edpt_close_all(uint8_t rhport)
static void handle_ctr_setup(uint32_t ep_id)
static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix)
static void edpt0_open(uint8_t rhport)
static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes)
static void handle_ctr_tx(uint32_t ep_id)
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type)
static void handle_ctr_rx(uint32_t ep_id)
static void handle_bus_reset(uint8_t rhport)
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const *request)
void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init)
static ep_alloc_t ep_alloc_status[FSDEV_EP_COUNT]
static uint16_t ep_buf_ptr
Points to first free memory location.
bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size)
static uint32_t dcd_pma_alloc(uint16_t len, bool dbuf)
void dcd_remote_wakeup(uint8_t rhport)
void dcd_sof_enable(uint8_t rhport, bool en)
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep)
static TU_ATTR_ALWAYS_INLINE uint16_t pma_align_buffer_size(uint16_t size, uint8_t *blsize, uint8_t *num_block)
static TU_ATTR_ALWAYS_INLINE void btable_set_count(uint32_t ep_id, uint8_t buf_id, uint16_t byte_count)
static TU_ATTR_ALWAYS_INLINE void ep_change_status(uint32_t *reg, tusb_dir_t dir, ep_stat_t state)
static TU_ATTR_ALWAYS_INLINE void btable_set_addr(uint32_t ep_id, uint8_t buf_id, uint16_t addr)
static TU_ATTR_ALWAYS_INLINE void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount)
static TU_ATTR_ALWAYS_INLINE uint32_t btable_get_addr(uint32_t ep_id, uint8_t buf_id)
static TU_ATTR_ALWAYS_INLINE void ep_change_dtog(uint32_t *reg, tusb_dir_t dir, uint8_t state)
static TU_ATTR_ALWAYS_INLINE void ep_write_clear_ctr(uint32_t ep_id, tusb_dir_t dir)
static TU_ATTR_ALWAYS_INLINE uint16_t btable_get_count(uint32_t ep_id, uint8_t buf_id)
AUDIO Channel Cluster Descriptor (4.1)
struct TU_ATTR_PACKED::@16::TU_ATTR_PACKED bmRequestType_bit
uint8_t bmAttributes
See: audio_clock_source_attribute_t.
uint8_t bRequest
Request type audio_cs_req_t.
volatile pma_access_scheme fsdev_bus_t value
static TU_ATTR_ALWAYS_INLINE uint16_t tu_min16(uint16_t x, uint16_t y)
void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info)
Get linear write info.
void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n)
Advance write pointer - intended to be used in combination with DMA. It is possible to fill the FIFO ...
void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n)
Advance read pointer - intended to be used in combination with DMA. It is possible to read from the F...
void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info)
Get read info.
static TU_ATTR_ALWAYS_INLINE uint8_t tu_edpt_number(uint8_t addr)
static TU_ATTR_ALWAYS_INLINE uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const *desc_ep)
TU_ATTR_PACKED_END TU_ATTR_BIT_FIELD_ORDER_END static TU_ATTR_ALWAYS_INLINE tusb_dir_t tu_edpt_dir(uint8_t addr)
CFG_TUH_MEM_ALIGN tusb_control_request_t request