diff options
| author | François Cartegnie <281376+fcartegnie@users.noreply.github.com> | 2024-08-20 13:43:09 +0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-20 13:43:09 +0700 |
| commit | f5874d607315ff88b27414299089b8528b5bb07c (patch) | |
| tree | 9db23b8e6cdfb06d8bab77e83224e604f20c4629 /src/usb/setup.c | |
| parent | b25d62d1362cfd711e6617a9212e3eddc4e9fddd (diff) | |
| parent | c3912e01a2767334103cd139d875d50c834f3f05 (diff) | |
Merge pull request #35 from kienvo/usb
feat: Receive data over USB
Diffstat (limited to 'src/usb/setup.c')
| -rw-r--r-- | src/usb/setup.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/src/usb/setup.c b/src/usb/setup.c new file mode 100644 index 0000000..d53c318 --- /dev/null +++ b/src/usb/setup.c @@ -0,0 +1,132 @@ +#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(); + + /* This should be placed first, the python script always looks + for the first interface (not the interface number) */ + hiddev_init(); + + cdc_acm_init(); + + init(); + PFIC_EnableIRQ(USB_IRQn); +}
\ No newline at end of file |