diff options
Diffstat (limited to 'src/usb/setup.c')
| -rw-r--r-- | src/usb/setup.c | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/src/usb/setup.c b/src/usb/setup.c new file mode 100644 index 0000000..b24fed0 --- /dev/null +++ b/src/usb/setup.c @@ -0,0 +1,126 @@ +#include <stdlib.h> + +#include "CH58x_common.h" + +#include "utils.h" + +uint8_t *cfg_desc; + +// FIXME: here wasting 1KiB of ram +void (*if_handlers[256])(USB_SETUP_REQ *request); +void (*ep_handlers[7])(); + +/* Configuration Descriptor template */ +USB_CFG_DESCR cfg_static = { + .bLength = sizeof(USB_CFG_DESCR), + .bDescriptorType = 0x02, + .wTotalLength = sizeof(USB_CFG_DESCR), // will be updated on cfg_desc_add() + .bNumInterfaces = 0, // will be updated on cfg_desc_add() + .bConfigurationValue = 0x01, + .iConfiguration = 4, + .bmAttributes = 0xA0, + .MaxPower = 50 // mA +}; + +void cfg_desc_append(void *desc) +{ + uint8_t cfg_len = 0; + uint8_t len = ((uint8_t *)desc)[0]; + if (cfg_desc) // attempting to add a non-Configuration Descriptor + cfg_len = ((USB_CFG_DESCR *)cfg_desc)->wTotalLength; + uint8_t newlen = cfg_len + len; + + cfg_desc = realloc(cfg_desc, newlen); // TODO: add a safe check here + + memcpy(cfg_desc + cfg_len, desc, len); + + ((USB_CFG_DESCR *)cfg_desc)->wTotalLength = newlen; + ((USB_CFG_DESCR *)cfg_desc)->bNumInterfaces += ((uint8_t *)desc)[1] == 0x04; +} + +int ep_cb_register(int ep_num, void (*cb)()) +{ + if (ep_num > 8) + return -1; + if (ep_handlers[ep_num]) // already registerd + return -1; + + ep_handlers[ep_num] = cb; + return 0; +} + +int if_cb_register(uint8_t if_num, void (*cb)(USB_SETUP_REQ *request)) +{ + if (if_handlers[if_num]) // already registered + return -1; + + if_handlers[if_num] = cb; + return 0; +} + +void dma_register(uint8_t ep_num, void *buf) +{ + if (ep_num > 7) // CH582 support only 8 endpoint + return; + + volatile uint16_t *p_regs[] = { + &R16_UEP0_DMA, + &R16_UEP1_DMA, + &R16_UEP2_DMA, + &R16_UEP3_DMA, + NULL, + &R16_UEP5_DMA, + &R16_UEP6_DMA, + &R16_UEP7_DMA, + }; + volatile uint8_t *ctrl_regs[] = { + &R8_UEP0_CTRL, + &R8_UEP1_CTRL, + &R8_UEP2_CTRL, + &R8_UEP3_CTRL, + &R8_UEP4_CTRL, + &R8_UEP5_CTRL, + &R8_UEP6_CTRL, + &R8_UEP7_CTRL, + }; + // ep4's dma buffer is hardcoded pointing to + // the next ep0 + if (ep_num != 4) + *p_regs[ep_num] = (uint16_t)(uint32_t)buf; + + *ctrl_regs[ep_num] = UEP_R_RES_ACK | UEP_T_RES_NAK; +} + +static void init(void) +{ + R8_USB_CTRL = 0x00; + + R8_UEP4_1_MOD = RB_UEP4_RX_EN | RB_UEP4_TX_EN | + RB_UEP1_RX_EN | RB_UEP1_TX_EN; + R8_UEP2_3_MOD = RB_UEP2_RX_EN | RB_UEP2_TX_EN | + RB_UEP3_RX_EN | RB_UEP3_TX_EN; + R8_UEP567_MOD = RB_UEP7_RX_EN | RB_UEP7_TX_EN | + RB_UEP6_RX_EN | RB_UEP6_TX_EN | + RB_UEP5_RX_EN | RB_UEP5_TX_EN; + + R16_PIN_ANALOG_IE |= RB_PIN_USB_IE | RB_PIN_USB_DP_PU; + R8_UDEV_CTRL = RB_UD_PD_DIS | RB_UD_PORT_EN; + + R8_USB_DEV_AD = 0x00; + R8_USB_INT_FG = 0xFF; + R8_USB_CTRL = RB_UC_DEV_PU_EN | RB_UC_INT_BUSY | RB_UC_DMA_EN; + R8_USB_INT_EN = RB_UIE_SUSPEND | RB_UIE_BUS_RST | RB_UIE_TRANSFER; +} + +void ctrl_init(); +void hiddev_init(); +void cdc_acm_init(); + +void usb_start() { + cfg_desc_append(&cfg_static); + + ctrl_init(); + + init(); + PFIC_EnableIRQ(USB_IRQn); +}
\ No newline at end of file |