#include "tusb_option.h"
#if TUSB_OPT_DEVICE_ENABLED && \
(CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X)
#include <stdint.h>
#include <ft900.h>
#include <registers/ft900_registers.h>
#include "board.h"
#include "bsp/board.h"
#define USBD_USE_STREAMS
#include "device/dcd.h"
extern int8_t board_ft90x_vbus(void);
static uint8_t _ft90x_setup_packet[8];
struct ft90x_xfer_state
{
volatile uint8_t valid; volatile int16_t total_size; volatile int16_t remain_size; volatile uint8_t *buff_ptr;
uint8_t type; uint8_t dir; uint16_t buff_size; uint16_t size; };
static struct ft90x_xfer_state ep_xfer[USBD_MAX_ENDPOINT_COUNT];
static tusb_speed_t _speed;
void _ft90x_usbd_ISR(void); void ft90x_usbd_pm_ISR(void);
static uint16_t _ft90x_edpt_xfer_out(uint8_t ep_number, uint8_t *buffer, uint16_t xfer_bytes);
static uint16_t _ft90x_edpt_xfer_in(uint8_t ep_number, uint8_t *buffer, uint16_t xfer_bytes);
static void _ft90x_reset_edpts(void);
static inline void _ft90x_phy_enable(bool en);
static void _ft90x_usb_speed(void);
static void _dcd_ft90x_attach(void);
static void _dcd_ft90x_detach(void) __attribute__((unused));
static uint16_t _ft90x_dusb_in(uint8_t ep_number, const uint8_t *buffer, uint16_t length);
static uint16_t _ft90x_dusb_out(uint8_t ep_number, uint8_t *buffer, uint16_t length);
static uint16_t _ft90x_edpt_xfer_out(uint8_t ep_number, uint8_t *buffer, uint16_t xfer_bytes)
{
uint16_t ep_size = ep_xfer[ep_number].size;
(void)ep_size;
if (xfer_bytes > ep_size)
{
xfer_bytes = ep_size;
}
xfer_bytes = _ft90x_dusb_out(ep_number, (uint8_t *)buffer, xfer_bytes);
if (ep_number == USBD_EP_0)
{
USBD_EP_SR_REG(USBD_EP_0) = (MASK_USBD_EP0SR_OPRDY);
}
else
{
USBD_EP_SR_REG(ep_number) = (MASK_USBD_EPxSR_OPRDY);
}
return xfer_bytes;
}
static uint16_t _ft90x_edpt_xfer_in(uint8_t ep_number, uint8_t *buffer, uint16_t xfer_bytes)
{
uint8_t end = 0;
uint16_t ep_size = ep_xfer[ep_number].size;
(void)ep_size;
if ((xfer_bytes == 0) || (xfer_bytes < ep_size))
{
end = 1;
}
else
{
xfer_bytes = ep_size;
}
if (ep_number == USBD_EP_0)
{
while (USBD_EP_SR_REG(USBD_EP_0) & MASK_USBD_EP0SR_STALL)
{
USBD_EP_SR_REG(USBD_EP_0) = (MASK_USBD_EP0SR_STALL);
}
}
else
{
uint8_t sr_reg;
do
{
sr_reg = USBD_EP_SR_REG(ep_number);
} while (sr_reg & MASK_USBD_EPxSR_INPRDY);
}
xfer_bytes = _ft90x_dusb_in(ep_number, (uint8_t *)buffer, xfer_bytes);
if (ep_number == USBD_EP_0)
{
if (end)
{
USBD_EP_SR_REG(USBD_EP_0) = MASK_USBD_EP0SR_INPRDY | MASK_USBD_EP0SR_DATAEND;
}
else
{
USBD_EP_SR_REG(USBD_EP_0) = (MASK_USBD_EP0SR_INPRDY);
}
}
else
{
USBD_EP_SR_REG(ep_number) = (MASK_USBD_EPxSR_INPRDY);
}
return xfer_bytes;
}
static void _ft90x_reset_edpts(void)
{
for (int i = 1; i < USBD_MAX_ENDPOINT_COUNT; i++)
{
tu_memclr(&ep_xfer[i], sizeof(struct ft90x_xfer_state));
USBD_EP_CR_REG(i) = 0;
}
USBD_REG(cmie) = MASK_USBD_CMIE_ALL;
}
static inline void _ft90x_phy_enable(bool en)
{
if (en)
SYS->PMCFG_L |= MASK_SYS_PMCFG_DEV_PHY_EN;
else
SYS->PMCFG_L &= ~MASK_SYS_PMCFG_DEV_PHY_EN;
}
static void _dcd_ft90x_attach(void)
{
uint8_t reg;
CRITICAL_SECTION_BEGIN
USBD_REG(faddr) = 0;
SYS->MSC0CFG = SYS->MSC0CFG | MASK_SYS_MSC0CFG_DEV_RESET_ALL;
SYS->PMCFG_H = MASK_SYS_PMCFG_DEV_DIS_DEV;
SYS->PMCFG_H = MASK_SYS_PMCFG_DEV_CONN_DEV;
SYS->PMCFG_L = SYS->PMCFG_L & (~MASK_SYS_PMCFG_DEV_DETECT_EN);
sys_enable(sys_device_usb_device);
CRITICAL_SECTION_END;
delayms(1);
CRITICAL_SECTION_BEGIN
#if BOARD_DEVICE_RHPORT_SPEED == OPT_MODE_HIGH_SPEED
USBD_REG(fctrl) = 0;
#else
USBD_REG(fctrl) = MASK_USBD_FCTRL_MODE_FS_ONLY;
#endif
do
{
reg = USBD_REG(cmif);
USBD_REG(cmif) = reg;
} while (reg);
reg = USBD_REG(epif);
USBD_REG(epif) = reg;
USBD_REG(cmie) = 0;
CRITICAL_SECTION_END;
SYS->PMCFG_L = SYS->PMCFG_L | MASK_SYS_PMCFG_DEV_DETECT_EN;
#if defined(__FT930__)
SYS->MSC0CFG = SYS->MSC0CFG | MASK_SYS_MSC0CFG_USB_VBUS_EN;
#endif
}
static void _dcd_ft90x_detach(void)
{
SYS->PMCFG_L = SYS->PMCFG_L & (~MASK_SYS_PMCFG_DEV_DETECT_EN);
#if defined(__FT930__)
SYS->MSC0CFG = SYS->MSC0CFG & (~MASK_SYS_MSC0CFG_USB_VBUS_EN);
#endif
CRITICAL_SECTION_BEGIN
USBD_REG(epie) = 0;
USBD_REG(cmie) = 0;
USBD_REG(fctrl) = 0;
CRITICAL_SECTION_END;
delayms(1);
dcd_disconnect(BOARD_DEVICE_RHPORT_NUM);
delayms(1);
sys_disable(sys_device_usb_device);
SYS->MSC0CFG = SYS->MSC0CFG | MASK_SYS_MSC0CFG_DEV_RESET_ALL;
delayms(1);
SYS->PMCFG_L = SYS->PMCFG_L | MASK_SYS_PMCFG_DEV_DETECT_EN;
#if defined(__FT930__)
SYS->MSC0CFG = SYS->MSC0CFG | MASK_SYS_MSC0CFG_USB_VBUS_EN;
#endif
}
static void _ft90x_usb_speed(void)
{
uint8_t fctrl_val;
if (USBD_REG(fctrl) & MASK_USBD_FCTRL_USB_DEV_EN) {
USBD_REG(fctrl) = (USBD_REG(fctrl) & (~MASK_USBD_FCTRL_USB_DEV_EN));
delayus(200);
}
#if BOARD_DEVICE_RHPORT_SPEED == OPT_MODE_HIGH_SPEED
fctrl_val = MASK_USBD_FCTRL_USB_DEV_EN;
#if defined(__FT900__)
if (!sys_check_ft900_revB()) {
fctrl_val |= MASK_USBD_FCTRL_IMP_PERF;
}
#endif
USBD_REG(fctrl) = fctrl_val;
#if defined(__FT930__)
delayus(200);
_speed = (SYS->MSC0CFG & MASK_SYS_MSC0CFG_HIGH_SPED_MODE) ?
TUSB_SPEED_HIGH : TUSB_SPEED_FULL;
#else
while (!(USBD_REG(cmif) & MASK_USBD_CMIF_SOFIRQ));
USBD_REG(cmif) = MASK_USBD_CMIF_SOFIRQ;
delayus(125 + 5);
_speed = (USBD_REG(cmif) & MASK_USBD_CMIF_SOFIRQ) ?
TUSB_SPEED_HIGH : TUSB_SPEED_FULL;
dcd_event_bus_reset(BOARD_DEVICE_RHPORT_NUM, _speed, true);
#endif
#else
_speed = TUSB_SPEED_FULL;
fctrl_val =
MASK_USBD_FCTRL_USB_DEV_EN | MASK_USBD_FCTRL_MODE_FS_ONLY;
#if defined(__FT900__)
if (!sys_check_ft900_revB()) {
fctrl_val |= MASK_USBD_FCTRL_IMP_PERF;
}
#endif
USBD_REG(fctrl) = fctrl_val;
dcd_event_bus_reset(BOARD_DEVICE_RHPORT_NUM, _speed, true);
return;
#endif }
static uint16_t _ft90x_dusb_in(uint8_t ep_number, const uint8_t *buffer, uint16_t length)
{
uint16_t bytes_read = 0;
uint16_t buff_size = length;
#ifdef USBD_USE_STREAMS
volatile uint8_t *data_reg;
data_reg = (volatile uint8_t *)&(USBD->ep[ep_number].epxfifo);
if (buff_size)
{
if (((uint32_t)buffer) % 4 == 0)
{
uint16_t aligned = buff_size & (~3);
uint16_t left = buff_size & 3;
if (aligned)
{
__asm__ volatile("streamout.l %0,%1,%2"
:
: "r"(data_reg), "r"(buffer), "r"(aligned));
buffer += aligned;
}
if (left)
{
__asm__ volatile("streamout.b %0,%1,%2"
:
: "r"(data_reg), "r"(buffer), "r"(left));
}
}
else
{
__asm__ volatile("streamout.b %0,%1,%2"
:
: "r"(data_reg), "r"(buffer), "r"(buff_size));
}
bytes_read = buff_size;
}
#else
bytes_read = buff_size;
while (buff_size--)
{
USBD_EP_FIFO_REG(ep_number) = *buffer++;
};
#endif
return bytes_read;
}
static uint16_t _ft90x_dusb_out(uint8_t ep_number, uint8_t *buffer, uint16_t length)
{
#ifdef USBD_USE_STREAMS
volatile uint8_t *data_reg;
#endif uint16_t bytes_read = 0;
uint16_t buff_size = length;
if (length > 0)
{
if (ep_number == USBD_EP_0)
{
buff_size = USBD_EP_CNT_REG(USBD_EP_0);
}
else
{
if (USBD_EP_SR_REG(ep_number) & (MASK_USBD_EPxSR_OPRDY))
{
buff_size = USBD_EP_CNT_REG(ep_number);
}
}
}
if (buff_size > length)
buff_size = length;
#ifdef USBD_USE_STREAMS
data_reg = (volatile uint8_t *)&(USBD->ep[ep_number].epxfifo);
if (buff_size)
{
if ((uint32_t)buffer % 4 == 0)
{
uint16_t aligned = buff_size & (~3);
uint16_t left = buff_size & 3;
if (aligned)
{
__asm__ volatile("streamin.l %0,%1,%2"
:
: "r"(buffer), "r"(data_reg), "r"(aligned));
buffer += aligned;
}
if (left)
{
__asm__ volatile("streamin.b %0,%1,%2"
:
: "r"(buffer), "r"(data_reg), "r"(left));
}
}
else
{
__asm__ volatile("streamin.b %0,%1,%2"
:
: "r"(buffer), "r"(data_reg), "r"(buff_size));
}
bytes_read = buff_size;
}
#else
bytes_read = buff_size;
while (buff_size--)
{
*buffer++ = USBD_EP_FIFO_REG(ep_number);
}
#endif
return bytes_read;
}
void dcd_init(uint8_t rhport)
{
TU_LOG2("FT90x initialisation\r\n");
_dcd_ft90x_attach();
interrupt_attach(interrupt_usb_device, (int8_t)interrupt_usb_device, _ft90x_usbd_ISR);
dcd_connect(rhport);
}
void dcd_int_enable(uint8_t rhport)
{
(void)rhport;
TU_LOG3("FT90x int enable\r\n");
interrupt_enable_globally();
}
void dcd_int_disable(uint8_t rhport)
{
(void)rhport;
TU_LOG3("FT90x int disable\r\n");
interrupt_disable_globally();
}
void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
{
(void)rhport;
(void)dev_addr;
dcd_edpt_xfer(rhport, tu_edpt_addr(USBD_EP_0, TUSB_DIR_IN), NULL, 0);
dev_addr |= 0x80;
CRITICAL_SECTION_BEGIN
{
USBD_REG(faddr) = dev_addr;
}
CRITICAL_SECTION_END;
}
#if 0#endif
void dcd_remote_wakeup(uint8_t rhport)
{
(void)rhport;
SYS->MSC0CFG = SYS->MSC0CFG | MASK_SYS_MSC0CFG_DEV_RMWAKEUP;
delayms(2);
SYS->MSC0CFG &= ~MASK_SYS_MSC0CFG_DEV_RMWAKEUP;
dcd_connect(rhport);
}
void dcd_connect(uint8_t rhport)
{
(void)rhport;
TU_LOG2("FT90x connect\r\n");
CRITICAL_SECTION_BEGIN
if (board_ft90x_vbus())
{
USBD_REG(faddr) = 0;
_ft90x_phy_enable(true);
_ft90x_usb_speed();
}
#if CFG_TUD_ENDPOINT0_SIZE == 64
USBD_EP_CR_REG(USBD_EP_0) = (USBD_EP0_MAX_SIZE_64 << BIT_USBD_EP0_MAX_SIZE);
#elif CFG_TUD_ENDPOINT0_SIZE == 32
USBD_EP_CR_REG(USBD_EP_0) = (USBD_EP0_MAX_SIZE_32 << BIT_USBD_EP0_MAX_SIZE);
#elif CFG_TUD_ENDPOINT0_SIZE == 16
USBD_EP_CR_REG(USBD_EP_0) = (USBD_EP0_MAX_SIZE_16 << BIT_USBD_EP0_MAX_SIZE);
#elif CFG_TUD_ENDPOINT0_SIZE == 8
USBD_EP_CR_REG(USBD_EP_0) = (USBD_EP0_MAX_SIZE_8 << BIT_USBD_EP0_MAX_SIZE);
#else
#error "CFG_TUD_ENDPOINT0_SIZE must be defined with a value of 8, 16, 32 or 64."
#endif
CRITICAL_SECTION_END;
ep_xfer[USBD_EP_0].size = CFG_TUD_ENDPOINT0_SIZE;
ep_xfer[USBD_EP_0].type = TUSB_XFER_CONTROL;
USBD_REG(epie) = (MASK_USBD_EPIE_EP0IE);
_ft90x_reset_edpts();
}
void dcd_disconnect(uint8_t rhport)
{
(void)rhport;
TU_LOG2("FT90x disconnect\r\n");
_ft90x_phy_enable(false);
}
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc)
{
(void)rhport;
uint8_t const ep_number = tu_edpt_number(ep_desc->bEndpointAddress);
uint8_t const ep_dir = tu_edpt_dir(ep_desc->bEndpointAddress);
uint8_t const ep_type = ep_desc->bmAttributes.xfer;
uint16_t const ep_size = tu_edpt_packet_size(ep_desc); uint16_t ep_buff_size;
uint8_t ep_reg_size = USBD_EP_MAX_SIZE_8;
uint8_t ep_reg_data = 0;
int16_t total_ram;
TU_LOG2("FT90x endpoint open %d %c\r\n", ep_number, ep_dir?'I':'O');
if (ep_number >= USBD_MAX_ENDPOINT_COUNT)
{
TU_LOG1("FT90x endpoint not valid: requested %d max %d\r\n", ep_number, USBD_MAX_ENDPOINT_COUNT);
return false;
}
while (ep_size > (8 * (1 << ep_reg_size)))
{
ep_reg_size++;
}
if (ep_reg_size > USBD_EP_MAX_SIZE_1024)
{
TU_LOG1("FT90x endpoint size not valid: requested %d max 1024\r\n", ep_size);
return false;
}
ep_buff_size = 8 << ep_reg_size;
if (ep_number > 0)
{
ep_reg_data |= (ep_reg_size << BIT_USBD_EP_MAX_SIZE);
if (ep_xfer[ep_number].type != USBD_EP_TYPE_DISABLED)
{
TU_LOG1("FT90x endpoint %d already assigned\r\n", ep_number);
return false;
}
if (ep_dir == USBD_DIR_IN)
total_ram = USBD_RAMTOTAL_IN;
else
total_ram = USBD_RAMTOTAL_OUT;
for (int i = 1; i < USBD_MAX_ENDPOINT_COUNT; i++)
{
if (ep_xfer[i].type != USBD_EP_TYPE_DISABLED)
{
if (ep_xfer[i].dir == ep_dir)
{
total_ram -= ep_xfer[i].buff_size;
}
}
}
total_ram -= ep_xfer[0].buff_size;
if (total_ram < ep_buff_size)
{
TU_LOG1("FT90x insufficient buffer RAM for endpoint %d\r\n", ep_number);
return false;
}
if (ep_type == USBD_EP_BULK)
ep_reg_data |= (USBD_EP_DIS_BULK << BIT_USBD_EP_CONTROL_DIS);
else if (ep_type == USBD_EP_INT)
ep_reg_data |= (USBD_EP_DIS_INT << BIT_USBD_EP_CONTROL_DIS);
else if (ep_type == USBD_EP_ISOC)
ep_reg_data |= (USBD_EP_DIS_ISO << BIT_USBD_EP_CONTROL_DIS);
if (ep_dir == USBD_DIR_IN)
ep_reg_data |= MASK_USBD_EPxCR_DIR;
USBD_EP_CR_REG(ep_number) = ep_reg_data;
TU_LOG2("FT90x endpoint setting %x\r\n", ep_reg_data);
}
else
{
USBD_EP_CR_REG(USBD_EP_0) = (ep_reg_size << BIT_USBD_EP0_MAX_SIZE);
}
ep_xfer[ep_number].dir = ep_dir;
ep_xfer[ep_number].type = ep_type;
ep_xfer[ep_number].size = ep_size;
ep_xfer[ep_number].buff_size = ep_buff_size;
CRITICAL_SECTION_BEGIN
ep_xfer[ep_number].valid = 0;
ep_xfer[ep_number].buff_ptr = NULL;
ep_xfer[ep_number].total_size = 0;
ep_xfer[ep_number].remain_size = 0;
CRITICAL_SECTION_END
return true;
}
void dcd_edpt_close_all(uint8_t rhport)
{
(void)rhport;
_ft90x_reset_edpts();
}
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
{
(void)rhport;
uint8_t ep_number = tu_edpt_number(ep_addr);
uint8_t dir = tu_edpt_dir(ep_addr);
uint16_t xfer_bytes;
bool status = false;
CRITICAL_SECTION_BEGIN
if (ep_xfer[ep_number].valid == 0)
{
status = true;
ep_xfer[ep_number].total_size = total_bytes;
ep_xfer[ep_number].remain_size = total_bytes;
ep_xfer[ep_number].buff_ptr = buffer;
ep_xfer[ep_number].valid = 1;
if (ep_number == USBD_EP_0)
{
ep_xfer[USBD_EP_0].dir = dir;
}
else
{
USBD_REG(epie) = USBD_REG(epie) | (1 << ep_number);
}
if (dir == TUSB_DIR_IN)
{
xfer_bytes = _ft90x_edpt_xfer_in(ep_number, buffer, total_bytes);
ep_xfer[ep_number].buff_ptr += xfer_bytes;
ep_xfer[ep_number].remain_size -= xfer_bytes;
}
}
CRITICAL_SECTION_END
return status;
}
bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes)
{
(void)rhport;
(void)ep_addr;
(void)ff;
(void)total_bytes;
bool status = false;
return status;
}
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
{
uint8_t ep_number = tu_edpt_number(ep_addr);
(void)rhport;
CRITICAL_SECTION_BEGIN
if (ep_number == USBD_EP_0)
{
USBD_EP_CR_REG(USBD_EP_0) = USBD_EP_CR_REG(USBD_EP_0) |
MASK_USBD_EP0CR_SDSTL;
}
else
{
USBD_EP_CR_REG(ep_number) = USBD_EP_CR_REG(ep_number) |
MASK_USBD_EPxCR_SDSTL;
USBD_EP_SR_REG(ep_number) = MASK_USBD_EPxSR_CLR_TOGGLE |
MASK_USBD_EPxSR_FIFO_FLUSH;
}
CRITICAL_SECTION_END
}
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
{
uint8_t ep_number = tu_edpt_number(ep_addr);
(void)rhport;
if (ep_number > USBD_EP_0)
{
CRITICAL_SECTION_BEGIN
USBD_EP_CR_REG(ep_number) = USBD_EP_CR_REG(ep_number) &
(~MASK_USBD_EPxCR_SDSTL);
USBD_EP_SR_REG(ep_number) = MASK_USBD_EPxSR_CLR_TOGGLE;
ep_xfer[ep_number].valid = 0;
ep_xfer[ep_number].remain_size = 0;
CRITICAL_SECTION_END
}
}
void _ft90x_usbd_ISR(void)
{
tud_int_handler(BOARD_DEVICE_RHPORT_NUM); }
void dcd_int_handler(uint8_t rhport)
{
(void)rhport;
uint8_t cmif = USBD_REG(cmif);
#if defined(__FT930__)
uint16_t epif = USBD_REG(epif);
#else
uint8_t epif = USBD_REG(epif);
#endif
if (cmif & MASK_USBD_CMIF_ALL)
{
USBD_REG(cmif) = MASK_USBD_CMIF_ALL;
if (cmif & MASK_USBD_CMIF_PHYIRQ) {
}
if (cmif & MASK_USBD_CMIF_PIDIRQ) {
}
if (cmif & MASK_USBD_CMIF_CRC16IRQ) {
}
if (cmif & MASK_USBD_CMIF_CRC5IRQ) {
}
if (cmif & MASK_USBD_CMIF_RSTIRQ) {
_ft90x_reset_edpts();
dcd_event_bus_reset(BOARD_DEVICE_RHPORT_NUM, _speed, true);
}
if (cmif & MASK_USBD_CMIF_SUSIRQ) {
dcd_event_bus_signal(BOARD_DEVICE_RHPORT_NUM, DCD_EVENT_SUSPEND, true);
}
if (cmif & MASK_USBD_CMIF_RESIRQ) {
dcd_event_bus_signal(BOARD_DEVICE_RHPORT_NUM, DCD_EVENT_RESUME, true);
}
if (cmif & MASK_USBD_CMIF_SOFIRQ) {
dcd_event_bus_signal(BOARD_DEVICE_RHPORT_NUM, DCD_EVENT_SOF, true);
}
}
if (epif)
{
uint16_t xfer_bytes;
if (epif & MASK_USBD_EPIF_EP0IRQ)
{
USBD_REG(epif) = MASK_USBD_EPIF_EP0IRQ;
if (USBD_EP_SR_REG(USBD_EP_0) & MASK_USBD_EP0SR_SETUP)
{
if (USBD_EP_CR_REG(USBD_EP_0) & MASK_USBD_EP0CR_SDSTL)
{
USBD_EP_CR_REG(USBD_EP_0) = USBD_EP_CR_REG(USBD_EP_0) &
(~MASK_USBD_EP0CR_SDSTL);
USBD_EP_SR_REG(USBD_EP_0) = MASK_USBD_EP0SR_STALL;
}
_ft90x_dusb_out(USBD_EP_0, (uint8_t *)_ft90x_setup_packet, sizeof(USB_device_request));
dcd_event_setup_received(BOARD_DEVICE_RHPORT_NUM, _ft90x_setup_packet, true);
USBD_EP_SR_REG(USBD_EP_0) = (MASK_USBD_EP0SR_SETUP);
ep_xfer[USBD_EP_0].valid = 0;
return;
}
else
{
if (ep_xfer[USBD_EP_0].valid)
{
xfer_bytes = (uint16_t)ep_xfer[USBD_EP_0].total_size;
if (ep_xfer[USBD_EP_0].dir == TUSB_DIR_OUT)
{
xfer_bytes = _ft90x_edpt_xfer_out(USBD_EP_0, (uint8_t *)ep_xfer[USBD_EP_0].buff_ptr, xfer_bytes);
}
dcd_event_xfer_complete(BOARD_DEVICE_RHPORT_NUM, (ep_xfer[USBD_EP_0].dir ? TUSB_DIR_IN_MASK : 0), xfer_bytes, XFER_RESULT_SUCCESS, true);
ep_xfer[USBD_EP_0].valid = 0;
}
}
}
else {
epif &= USBD_REG(epie);
for (uint8_t ep_number = 1; ep_number < USBD_MAX_ENDPOINT_COUNT; ep_number++)
{
if ((epif & MASK_USBD_EPIF_IRQ(ep_number)) == 0)
{
continue;
}
if (ep_xfer[ep_number].valid)
{
xfer_bytes = 0;
uint8_t ep_dirmask = (ep_xfer[ep_number].dir ? TUSB_DIR_IN_MASK : 0);
USBD_REG(epif) = MASK_USBD_EPIF_IRQ(ep_number);
if (ep_xfer[ep_number].dir == TUSB_DIR_OUT)
{
xfer_bytes = _ft90x_edpt_xfer_out(ep_number,
(uint8_t *)ep_xfer[ep_number].buff_ptr,
(uint16_t)ep_xfer[ep_number].remain_size);
ep_xfer[ep_number].buff_ptr += xfer_bytes;
ep_xfer[ep_number].remain_size -= xfer_bytes;
}
else {
if (ep_xfer[ep_number].remain_size > 0)
{
xfer_bytes = _ft90x_edpt_xfer_in(ep_number,
(uint8_t *)ep_xfer[ep_number].buff_ptr,
(uint16_t)ep_xfer[ep_number].remain_size);
ep_xfer[ep_number].buff_ptr += xfer_bytes;
ep_xfer[ep_number].remain_size -= xfer_bytes;
}
}
if (ep_xfer[ep_number].remain_size == 0)
{
dcd_event_xfer_complete(BOARD_DEVICE_RHPORT_NUM, ep_number | ep_dirmask, ep_xfer[ep_number].total_size, XFER_RESULT_SUCCESS, true);
ep_xfer[ep_number].valid = 0;
USBD_REG(epie) = USBD_REG(epie) & (~(1 << ep_number));
}
}
}
}
}
}
void ft90x_usbd_pm_ISR(void)
{
uint16_t pmcfg = SYS->PMCFG_H;
if (pmcfg & MASK_SYS_PMCFG_DEV_CONN_DEV)
{
SYS->PMCFG_H = MASK_SYS_PMCFG_PM_GPIO_IRQ_PEND;
dcd_event_bus_signal(BOARD_DEVICE_RHPORT_NUM, DCD_EVENT_RESUME, true);
}
if (pmcfg & MASK_SYS_PMCFG_DEV_DIS_DEV)
{
SYS->PMCFG_H = MASK_SYS_PMCFG_PM_GPIO_IRQ_PEND;
dcd_event_bus_signal(BOARD_DEVICE_RHPORT_NUM, DCD_EVENT_UNPLUGGED, true);
}
if (pmcfg & MASK_SYS_PMCFG_HOST_RST_DEV)
{
SYS->PMCFG_H = MASK_SYS_PMCFG_PM_GPIO_IRQ_PEND;
dcd_event_bus_signal(BOARD_DEVICE_RHPORT_NUM, DCD_EVENT_BUS_RESET, true);
}
if (pmcfg & MASK_SYS_PMCFG_HOST_RESUME_DEV)
{
SYS->PMCFG_H = MASK_SYS_PMCFG_PM_GPIO_IRQ_PEND;
if (!(SYS->MSC0CFG & MASK_SYS_MSC0CFG_DEV_RMWAKEUP))
{
dcd_event_bus_signal(BOARD_DEVICE_RHPORT_NUM, DCD_EVENT_RESUME, true);
}
}
}
#endif