#ifndef CORE_USB_USB_DRIVER #define CORE_USB_USB_DRIVER //#include "utils/gen_queue.h" #include "usb_common_types.h" //#define USBDBGMSG #define USB_NUM_OF_ENDPOINTS (4) #define USB_MAX_FS_PCKT_SIZE_NON_ISOCHRONOUS (64) #define USB_MAX_FS_PCKT_SIZE_ISOCHRONOUS (1023) #define USB_MIN_EP_FIFO_SIZE (64) // endpoint configuration structure typedef struct { uint16_t max_packet_size; // maximum packet size bool8_t responding_NAK; // indicates if endpoint responds with NAK uint8_t type; // endpoint type uint8_t service_interval; // service interval // calculated values uint8_t is_configured; // the endpoint is in use uint16_t fifo_address; // address in the FIFO uint16_t fifo_size; // FIFO size bool8_t zlp_next; // indicates, that ZLP should be transmitted at the end of the current transfer } USBDRV_EpConfig; typedef enum { USB_FSM_INITIAL_WAIT_SPEEDNEG = 0, // initial state, right after reset, wait for speed negotiation, must be ZERO! USB_FSM_SETUP_OPERATE, // ready to perform setup operations } USBDRV_FsmState; typedef enum { USB_EVT_USB_RESET, // bus reset received USB_EVT_SPEEDNEG_DONE, // linespeed negotiation (ST calls "enumeration") done USB_EVT_RECEPTION_DONE, // received packet is waiting to be fetched from the Rx FIFO USB_EVT_OUT_DONE, // something has happened on an OUT endpoint USB_EVT_IN_DONE, // previously armed IN endpoint has finished packet transmission } USBDRV_EventCode; // endpoint event typedef enum { USB_EPEVT_IDLE = 0x00, // endpoint is IDLE USB_EPEVT_ARMED, // endpoint is armed for transmission USB_EPEVT_STALLED, // endpoint is stalled USB_EPEVT_NAK // endpoint responds NAK regardless of FIFO level } USBDRV_EndpointEvent; // USB device state typedef struct { USBDRV_EpConfig ep_OUT[USB_NUM_OF_ENDPOINTS]; // OUT endpoint configs USBDRV_EpConfig ep_IN[USB_NUM_OF_ENDPOINTS]; // IN endpoint configs uint16_t rx_fifo_size; // Rx FIFO size in bytes uint16_t state; // FSM state uint8_t *rx_buf; // pointer to the receive buffer (this way declaration can be separated) uint16_t rx_buf_level; // fill level of the rx buffer // Queue *event_queue; // event queue uint8_t address; // device address } USBDRV_GlobalState; // USB received packet status typedef enum { USB_PCKT_STATUS_GLOBAL_OUT_NAK = 0b0001, USB_PCKT_STATUS_OUT_DATA_RECV = 0b0010, USB_PCKT_STATUS_OUT_TRANSFER_CPLT = 0b0011, USB_PCKT_STATUS_SETUP_CPLT = 0b0100, USB_PCKT_STATUS_SETUP_DATA_RECV = 0b0110, } USBDRV_PcktStatus; #define USB_FLUSH_TX_FIFO_ALL (0b10000) // event data typedef union { struct { uint8_t pckt_status; // read packet status uint8_t data_pid; // data PID uint8_t byte_count; // byte count uint8_t ep_num; // read endpoint number } rx; // receive event data } USBDRV_EventData; // event compound for queueing typedef struct { uint32_t code; // event code USBDRV_EventData data; // accompaining event data } USBDRV_EventCompound; // callback codes typedef enum { USB_CBC_OUT, // OUT done! USB_CBC_IN_DONE, // IN done! USB_CBC_IN_FIFOEMPTY, // could not serve IN request, since Tx FIFO was empty } USBDRV_CallbackCode; // callback compound typedef struct { uint8_t ep : 4; // endpoint number uint8_t dir : 1; // direction uint8_t code : 3; // event code uint16_t size; // data size const uint8_t *data; // data } USBDRV_CallbackCompound; typedef enum { UST_SETUP, UST_DATA } USBDRV_ControlTfStage; // ------------ void usbdrv_gpio_init(); // USB pin low level, early peripheral initialization void usbdrv_init_global_state(); // initialize global state void usbdrv_periph_init(); // initialize USB peripheral void usbdrv_initial_ep0_setup(); // create an initial setup for EP0 in both directions void usbdrv_power_and_connect(bool en); // connect to or disconnect from the bus void usbdrv_init(); // initialize USB subsystem void usbdrv_reset(); // reset USB subsystem void usbdrv_preload_endpoint_config(uint8_t ep, uint8_t dir, const USBDRV_EpConfig *cfg); // preload usb endpoint config void usbdrv_clear_endpoint_config(); // clear endpoint config void usbdrv_apply_endpoint_config(); // apply preloaded endpoint configuration void usbdrv_build_fifo(); // build FIFO (compute addresses) void usbdrv_fetch_endpoint_configuration(uint8_t config_index); // fetch endpoint configuration from descriptor dump void usbdrv_configure_endpoint(uint8_t ep, uint8_t dir, const USBDRV_EpConfig *cfg); // configure USB endpoint void usbdrv_deconfigure_endpoint(uint8_t ep, uint8_t dir); // deconfigure USB endpoint void usbdrv_stall_endpoint(uint8_t ep, uint8_t dir, bool stall); // stall endpoint void usbdrv_set_global_NAK(uint8_t dir, bool en); // set global NAK void usbdrv_flush_tx_fifo(uint8_t n); // flush specific or all Tx FIFOs void usbdrv_flush_rx_fifo(); // flush the Rx FIFO void usbdrv_set_rx_fifo_size(uint16_t size); // set Rx FIFO size void usbdrv_fetch_received_data(uint8_t ep, uint16_t len); // fetch received data from RX FIFO to receive buffer void usbdrv_process_rx_fifo_top(USBDRV_EventData *evt_data); // see what's on top of Rx FIFO uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len); // write data to specific endpoint FIFO #define USBDRV_ARM_IN_ZLP(ep) usbdrv_arm_IN_endpoint((ep), NULL, 0) void usbdrv_arm_OUT_endpoint(uint8_t ep, uint8_t size); // arm OUT endpoint bool usbdrv_get_endpoint_interrupt_flag(uint8_t ep, uint8_t dir); // get endpoint interrupt flag void usbdrv_set_address(uint8_t addr); // set device address void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data); // process USB event void usbdrv_push_event(uint32_t evt_code, USBDRV_EventData *evt_data); // push event onto the event queue void usbdrv_periodic_processing(); // call this to process incoming events #endif /* CORE_USB_USB_DRIVER */