Add USB Host registers and types and LL layer

This commit adds the register struct, Low Level Layer, and
protocol types for USB Host
This commit is contained in:
Darian Leung
2020-12-18 00:33:50 +08:00
parent 45afa158ff
commit 602a747b31
4 changed files with 2444 additions and 0 deletions

View File

@@ -28,4 +28,5 @@ PROVIDE ( TWAI = 0x3f42B000 );
PROVIDE ( APB_SARADC = 0x3f440000 );
PROVIDE ( DEDIC_GPIO = 0x3f4cf000 );
PROVIDE ( USB0 = 0x60080000 );
PROVIDE ( USBH = 0x60080000 );
PROVIDE ( USB_WRAP = 0x3f439000 );

View File

@@ -0,0 +1,886 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
#include "soc/usbh_struct.h"
#include "soc/usb_wrap_struct.h"
#include "hal/usb_types.h"
/* -----------------------------------------------------------------------------
------------------------------- Global Registers -------------------------------
----------------------------------------------------------------------------- */
/*
* Interrupt bit masks of the GINTSTS and GINTMSK registers
*/
#define USB_LL_INTR_CORE_WKUPINT (1 << 31)
#define USB_LL_INTR_CORE_SESSREQINT (1 << 30)
#define USB_LL_INTR_CORE_DISCONNINT (1 << 29)
#define USB_LL_INTR_CORE_CONIDSTSCHNG (1 << 28)
#define USB_LL_INTR_CORE_PTXFEMP (1 << 26)
#define USB_LL_INTR_CORE_HCHINT (1 << 25)
#define USB_LL_INTR_CORE_PRTINT (1 << 24)
#define USB_LL_INTR_CORE_RESETDET (1 << 23)
#define USB_LL_INTR_CORE_FETSUSP (1 << 22)
#define USB_LL_INTR_CORE_INCOMPIP (1 << 21)
#define USB_LL_INTR_CORE_INCOMPISOIN (1 << 20)
#define USB_LL_INTR_CORE_OEPINT (1 << 19)
#define USB_LL_INTR_CORE_IEPINT (1 << 18)
#define USB_LL_INTR_CORE_EPMIS (1 << 17)
#define USB_LL_INTR_CORE_EOPF (1 << 15)
#define USB_LL_INTR_CORE_ISOOUTDROP (1 << 14)
#define USB_LL_INTR_CORE_ENUMDONE (1 << 13)
#define USB_LL_INTR_CORE_USBRST (1 << 12)
#define USB_LL_INTR_CORE_USBSUSP (1 << 11)
#define USB_LL_INTR_CORE_ERLYSUSP (1 << 10)
#define USB_LL_INTR_CORE_GOUTNAKEFF (1 << 7)
#define USB_LL_INTR_CORE_GINNAKEFF (1 << 6)
#define USB_LL_INTR_CORE_NPTXFEMP (1 << 5)
#define USB_LL_INTR_CORE_RXFLVL (1 << 4)
#define USB_LL_INTR_CORE_SOF (1 << 3)
#define USB_LL_INTR_CORE_OTGINT (1 << 2)
#define USB_LL_INTR_CORE_MODEMIS (1 << 1)
#define USB_LL_INTR_CORE_CURMOD (1 << 0)
/*
* Bit mask of interrupt generating bits of the the HPRT register. These bits
* are ORd into the USB_LL_INTR_CORE_PRTINT interrupt.
*
* Note: Some fields of the HPRT are W1C (write 1 clear), this we cannot do a
* simple read and write-back to clear the HPRT interrupt bits. Instead we need
* a W1C mask the non-interrupt related bits
*/
#define USBH_LL_HPRT_W1C_MSK (0x2E)
#define USBH_LL_HPRT_ENA_MSK (0x04)
#define USBH_LL_INTR_HPRT_PRTOVRCURRCHNG (1 << 5)
#define USBH_LL_INTR_HPRT_PRTENCHNG (1 << 3)
#define USBH_LL_INTR_HPRT_PRTCONNDET (1 << 1)
/*
* Bit mask of channel interrupts (HCINTi and HCINTMSKi registers)
*
* Note: Under Scatter/Gather DMA mode, only the following interrupts can be unmasked
* - DESC_LS_ROLL
* - XCS_XACT_ERR (always unmasked)
* - BNAINTR
* - CHHLTD
* - XFERCOMPL
* The remaining interrupt bits will still be set (when the corresponding event occurs)
* but will not generate an interrupt. Therefore we must proxy through the
* USBH_LL_INTR_CHAN_CHHLTD interrupt to check the other interrupt bits.
*/
#define USBH_LL_INTR_CHAN_DESC_LS_ROLL (1 << 13)
#define USBH_LL_INTR_CHAN_XCS_XACT_ERR (1 << 12)
#define USBH_LL_INTR_CHAN_BNAINTR (1 << 11)
#define USBH_LL_INTR_CHAN_DATATGLERR (1 << 10)
#define USBH_LL_INTR_CHAN_FRMOVRUN (1 << 9)
#define USBH_LL_INTR_CHAN_BBLEER (1 << 8)
#define USBH_LL_INTR_CHAN_XACTERR (1 << 7)
#define USBH_LL_INTR_CHAN_NYET (1 << 6)
#define USBH_LL_INTR_CHAN_ACK (1 << 5)
#define USBH_LL_INTR_CHAN_NAK (1 << 4)
#define USBH_LL_INTR_CHAN_STALL (1 << 3)
#define USBH_LL_INTR_CHAN_AHBERR (1 << 2)
#define USBH_LL_INTR_CHAN_CHHLTD (1 << 1)
#define USBH_LL_INTR_CHAN_XFERCOMPL (1 << 0)
/*
* QTD (Queue Transfer Descriptor) structure used in Scatter/Gather DMA mode.
* Each QTD describes one transfer. Scatter gather mode will automatically split
* a transfer into multiple MPS packets. Each QTD is 64bits in size
*
* Note: The status information part of the QTD is interpreted differently depending
* on IN or OUT, and ISO or non-ISO
*/
typedef struct {
union {
struct {
uint32_t xfer_size: 17;
uint32_t aqtd_offset: 6;
uint32_t aqtd_valid: 1;
uint32_t reserved_24: 1;
uint32_t intr_cplt: 1;
uint32_t eol: 1;
uint32_t reserved_27: 1;
uint32_t rx_status: 2;
uint32_t reserved_30: 1;
uint32_t active: 1;
} in_non_iso;
struct {
uint32_t xfer_size: 12;
uint32_t reserved_12_24: 13;
uint32_t intr_cplt: 1;
uint32_t reserved_26_27: 2;
uint32_t rx_status: 2;
uint32_t reserved_30: 1;
uint32_t active: 1;
} in_iso;
struct {
uint32_t xfer_size: 17;
uint32_t reserved_17_23: 7;
uint32_t is_setup: 1;
uint32_t intr_cplt: 1;
uint32_t eol: 1;
uint32_t reserved_27: 1;
uint32_t tx_status: 2;
uint32_t reserved_30: 1;
uint32_t active: 1;
} out_non_iso;
struct {
uint32_t xfer_size: 12;
uint32_t reserved_12_24: 13;
uint32_t intr_cplt: 1;
uint32_t eol: 1;
uint32_t reserved_27: 1;
uint32_t tx_status: 2;
uint32_t reserved_30: 1;
uint32_t active: 1;
} out_iso;
uint32_t buffer_status_val;
};
void *buffer;
} usbh_ll_dma_qtd_t;
/*
* Enumeration of different possible lengths of the periodic frame list
*/
typedef enum {
USBH_LL_FRAME_LIST_LEN_8 = 0,
USBH_LL_FRAME_LIST_LEN_16,
USBH_LL_FRAME_LIST_LEN_32,
USBH_LL_FRAME_LIST_LEN_64,
} usbh_ll_frame_list_len_t;
/* -----------------------------------------------------------------------------
------------------------------ USB Wrap Registers ------------------------------
----------------------------------------------------------------------------- */
/**
* @brief Configures the internal PHY to operate as HOST
*
* @param hw Start address of the USB Wrap registers
*/
static inline void usbh_ll_internal_phy_conf(usb_wrap_dev_t *hw)
{
//Enable internal PHY
hw->otg_conf.pad_enable = 1;
hw->otg_conf.phy_sel = 0;
//Set pulldowns on D+ and D-
hw->otg_conf.pad_pull_override = 1;
hw->otg_conf.dp_pulldown = 1;
hw->otg_conf.dm_pulldown = 1;
}
/* -----------------------------------------------------------------------------
------------------------------- Global Registers -------------------------------
----------------------------------------------------------------------------- */
// --------------------------- GAHBCFG Register --------------------------------
static inline void usb_ll_en_dma_mode(usbh_dev_t *hw)
{
hw->gahbcfg_reg.dmaen = 1;
}
static inline void usb_ll_en_slave_mode(usbh_dev_t *hw)
{
hw->gahbcfg_reg.dmaen = 0;
}
static inline void usb_ll_set_hbstlen(usbh_dev_t *hw, uint32_t burst_len)
{
hw->gahbcfg_reg.hbstlen = burst_len;
}
static inline void usb_ll_en_global_intr(usbh_dev_t *hw)
{
hw->gahbcfg_reg.glbllntrmsk = 1;
}
static inline void usb_ll_dis_global_intr(usbh_dev_t *hw)
{
hw->gahbcfg_reg.glbllntrmsk = 0;
}
// --------------------------- GUSBCFG Register --------------------------------
static inline void usb_ll_set_host_mode(usbh_dev_t *hw)
{
hw->gusbcfg_reg.forcehstmode = 1;
}
static inline void usb_ll_dis_hnp_cap(usbh_dev_t *hw)
{
hw->gusbcfg_reg.hnpcap = 0;
}
static inline void usb_ll_dis_srp_cap(usbh_dev_t *hw)
{
hw->gusbcfg_reg.srpcap = 0;
}
// --------------------------- GRSTCTL Register --------------------------------
static inline bool usb_ll_check_ahb_idle(usbh_dev_t *hw)
{
return hw->grstctl_reg.ahbidle;
}
static inline bool usb_ll_check_dma_req_in_progress(usbh_dev_t *hw)
{
return hw->grstctl_reg.dmareq;
}
static inline void usb_ll_flush_tx_fifo(usbh_dev_t *hw, uint32_t chan_num)
{
usb_grstctl_reg_t grstctl;
grstctl.val = hw->grstctl_reg.val;
grstctl.txfnum = chan_num; //Set channel number to flush
grstctl.txfflsh = 1; //Flush that channel's TX FIFO
hw->grstctl_reg.val = grstctl.val;
}
static inline void usb_ll_flush_rx_fifo(usbh_dev_t *hw)
{
hw->grstctl_reg.rxfflsh = 1;
}
static inline void usb_ll_reset_frame_counter(usbh_dev_t *hw)
{
hw->grstctl_reg.frmcntrrst = 1;
}
// --------------------------- GINTSTS Register --------------------------------
/**
* @brief Reads and clears the global interrupt register
*
* @param hw
* @return uint32_t
*/
static inline uint32_t usb_ll_intr_read_and_clear(usbh_dev_t *hw)
{
usb_gintsts_reg_t gintsts;
gintsts.val = hw->gintsts_reg.val;
hw->gintsts_reg.val = gintsts.val; //Write back to clear
return gintsts.val;
}
// --------------------------- GINTMSK Register --------------------------------
static inline void usb_ll_en_intrs(usbh_dev_t *hw, uint32_t intr_mask)
{
hw->gintmsk_reg.val |= intr_mask;
}
static inline void usb_ll_dis_intrs(usbh_dev_t *hw, uint32_t intr_mask)
{
hw->gintmsk_reg.val &= ~intr_mask;
}
// --------------------------- GRXFSIZ Register --------------------------------
static inline void usb_ll_set_rx_fifo_size(usbh_dev_t *hw, uint32_t size)
{
//Set size in words
hw->grxfsiz_reg.rxfdep = size;
}
// -------------------------- GNPTXFSIZ Register -------------------------------
static inline void usb_ll_set_nptx_fifo_size(usbh_dev_t *hw, uint32_t addr, uint32_t size)
{
usb_gnptxfsiz_reg_t gnptxfsiz;
gnptxfsiz.val = hw->gnptxfsiz_reg.val;
gnptxfsiz.nptxfstaddr = addr;
gnptxfsiz.nptxfdep = size;
hw->gnptxfsiz_reg.val = gnptxfsiz.val;
}
static inline uint32_t usb_ll_get_controller_core_id(usbh_dev_t *hw)
{
return hw->gsnpsid_reg.val;
}
/**
* @brief Get the hardware configuration regiters of the DWC_OTG controller
*
* The hardware configuraiton regitsers are read only and indicate the various
* features of the DWC_OTG core.
*
* @param hw Start address of the DWC_OTG registers
* @param[out] ghwcfg1 Hardware configuration registesr 1
* @param[out] ghwcfg2 Hardware configuration registesr 2
* @param[out] ghwcfg3 Hardware configuration registesr 3
* @param[out] ghwcfg4 Hardware configuration registesr 4
*/
static inline void usb_ll_get_hardware_config(usbh_dev_t *hw, uint32_t *ghwcfg1, uint32_t *ghwcfg2, uint32_t *ghwcfg3, uint32_t *ghwcfg4)
{
*ghwcfg1 = hw->ghwcfg1_reg.val;
*ghwcfg2 = hw->ghwcfg2_reg.val;
*ghwcfg3 = hw->ghwcfg3_reg.val;
*ghwcfg4 = hw->ghwcfg4_reg.val;
}
// --------------------------- HPTXFSIZ Register -------------------------------
static inline void usbh_ll_set_ptx_fifo_size(usbh_dev_t *hw, uint32_t addr, uint32_t size)
{
usb_hptxfsiz_reg_t hptxfsiz;
hptxfsiz.val = hw->hptxfsiz_reg.val;
hptxfsiz.ptxfstaddr = addr;
hptxfsiz.ptxfsize = size;
hw->hptxfsiz_reg.val = hptxfsiz.val;
}
/* -----------------------------------------------------------------------------
-------------------------------- Host Registers --------------------------------
----------------------------------------------------------------------------- */
// ----------------------------- HCFG Register ---------------------------------
static inline void usbh_ll_hcfg_en_perio_sched(usbh_dev_t *hw)
{
hw->hcfg_reg.perschedena = 1;
}
static inline void usbh_ll_hcfg_dis_perio_sched(usbh_dev_t *hw)
{
hw->hcfg_reg.perschedena = 0;
}
/**
* Sets the length of the frame list
*
* @param num_entires Number of entires in the frame list
*/
static inline void usbh_ll_hcfg_set_num_frame_list_entries(usbh_dev_t *hw, usbh_ll_frame_list_len_t num_entries)
{
hw->hcfg_reg.frlisten = num_entries;
}
static inline void usbh_ll_hcfg_en_scatt_gatt_dma(usbh_dev_t *hw)
{
hw->hcfg_reg.descdma = 1;
}
static inline void usbh_ll_hcfg_set_fsls_supp_only(usbh_dev_t *hw)
{
hw->hcfg_reg.fslssupp = 1;
}
static inline void usbh_ll_hcfg_set_fsls_pclk_sel(usbh_dev_t *hw)
{
hw->hcfg_reg.fslspclksel = 1;
}
/**
* @brief Sets some default values to HCFG to operate in Host mode wiht scatter/gather DMA
*
* @param hw
*/
static inline void usbh_ll_hcfg_set_defaults(usbh_dev_t *hw)
{
hw->hcfg_reg.descdma = 1; //Enable scatt/gatt
hw->hcfg_reg.fslssupp = 1; //FS/LS supp only
hw->hcfg_reg.fslspclksel = 1; //48MHz PHY clock
hw->hcfg_reg.perschedena = 0; //Disable perio sched
}
// ----------------------------- HFIR Register ---------------------------------
static inline void usbh_ll_hfir_set_defaults(usbh_dev_t *hw)
{
usb_hfir_reg_t hfir;
hfir.val = hw->hfir_reg.val;
hfir.hfirrldctrl = 0; //Disable dynamic loading
hfir.frint = 48000; //Set frame interval to 48000 cycles of 48KHz clock (1ms)
hw->hfir_reg.val = hfir.val;
}
// ----------------------------- HFNUM Register --------------------------------
static inline uint32_t usbh_ll_get_frm_time_rem(usbh_dev_t *hw)
{
return hw->hfnum_reg.frrem;
}
static inline uint32_t usbh_ll_get_frm_num(usbh_dev_t *hw)
{
return hw->hfnum_reg.frnum;
}
// ---------------------------- HPTXSTS Register -------------------------------
static inline uint32_t usbh_ll_get_p_tx_queue_top(usbh_dev_t *hw)
{
return hw->hptxsts_reg.ptxqtop;
}
static inline uint32_t usbh_ll_get_p_tx_queue_space_avail(usbh_dev_t *hw)
{
return hw->hptxsts_reg.ptxqspcavail;
}
static inline uint32_t usbh_ll_get_p_tx_fifo_space_avail(usbh_dev_t *hw)
{
return hw->hptxsts_reg.ptxfspcavail;
}
// ----------------------------- HAINT Register --------------------------------
static inline uint32_t usbh_ll_get_chan_intrs_msk(usbh_dev_t *hw)
{
return hw->haint_reg.haint;
}
// --------------------------- HAINTMSK Register -------------------------------
static inline void usbh_ll_haintmsk_en_chan_intr(usbh_dev_t *hw, uint32_t mask)
{
hw->haintmsk_reg.val |= mask;
}
static inline void usbh_ll_haintmsk_dis_chan_intr(usbh_dev_t *hw, uint32_t mask)
{
hw->haintmsk_reg.val &= ~mask;
}
// --------------------------- HFLBAddr Register -------------------------------
static inline void usbh_ll_set_frame_list_base_addr(usbh_dev_t *hw, uint32_t addr)
{
hw->hflbaddr_reg.hflbaddr = addr;
}
static inline uint32_t usbh_ll_get_frame_list_base_addr(usbh_dev_t *hw)
{
return hw->hflbaddr_reg.hflbaddr;
}
// ----------------------------- HPRT Register ---------------------------------
static inline usb_speed_t usbh_ll_hprt_get_speed(usbh_dev_t *hw)
{
int prtspd = hw->hprt_reg.prtspd;
if (prtspd == 1) {
return USB_SPEED_FULL;
} else {
return USB_SPEED_LOW;
}
}
static inline uint32_t usbh_ll_hprt_get_test_ctl(usbh_dev_t *hw)
{
return hw->hprt_reg.prttstctl;
}
static inline void usbh_ll_hprt_set_test_ctl(usbh_dev_t *hw, uint32_t test_mode)
{
usb_hprt_reg_t hprt;
hprt.val = hw->hprt_reg.val;
hprt.prttstctl = test_mode;
hw->hprt_reg.val = hprt.val & (~USBH_LL_HPRT_W1C_MSK);
}
static inline void usbh_ll_hprt_en_pwr(usbh_dev_t *hw)
{
usb_hprt_reg_t hprt;
hprt.val = hw->hprt_reg.val;
hprt.prtpwr = 1;
hw->hprt_reg.val = hprt.val & (~USBH_LL_HPRT_W1C_MSK);
}
static inline void usbh_ll_hprt_dis_pwr(usbh_dev_t *hw)
{
usb_hprt_reg_t hprt;
hprt.val = hw->hprt_reg.val;
hprt.prtpwr = 0;
hw->hprt_reg.val = hprt.val & (~USBH_LL_HPRT_W1C_MSK);
}
static inline uint32_t usbh_ll_hprt_get_pwr_line_status(usbh_dev_t *hw)
{
return hw->hprt_reg.prtlnsts;
}
static inline void usbh_ll_hprt_set_port_reset(usbh_dev_t *hw, bool reset)
{
usb_hprt_reg_t hprt;
hprt.val = hw->hprt_reg.val;
hprt.prtrst = reset;
hw->hprt_reg.val = hprt.val & (~USBH_LL_HPRT_W1C_MSK);
}
static inline bool usbh_ll_hprt_get_port_reset(usbh_dev_t *hw)
{
return hw->hprt_reg.prtrst;
}
static inline void usbh_ll_hprt_set_port_suspend(usbh_dev_t *hw)
{
usb_hprt_reg_t hprt;
hprt.val = hw->hprt_reg.val;
hprt.prtsusp = 1;
hw->hprt_reg.val = hprt.val & (~USBH_LL_HPRT_W1C_MSK);
}
static inline bool usbh_ll_hprt_get_port_suspend(usbh_dev_t *hw)
{
return hw->hprt_reg.prtsusp;
}
static inline void usbh_ll_hprt_set_port_resume(usbh_dev_t *hw)
{
usb_hprt_reg_t hprt;
hprt.val = hw->hprt_reg.val;
hprt.prtres = 1;
hw->hprt_reg.val = hprt.val & (~USBH_LL_HPRT_W1C_MSK);
}
static inline void usbh_ll_hprt_clr_port_resume(usbh_dev_t *hw)
{
usb_hprt_reg_t hprt;
hprt.val = hw->hprt_reg.val;
hprt.prtres = 0;
hw->hprt_reg.val = hprt.val & (~USBH_LL_HPRT_W1C_MSK);
}
static inline bool usbh_ll_hprt_get_port_resume(usbh_dev_t *hw)
{
return hw->hprt_reg.prtres;
}
static inline bool usbh_ll_hprt_get_port_overcur(usbh_dev_t *hw)
{
return hw->hprt_reg.prtovrcurract;
}
static inline bool usbh_ll_hprt_get_port_en(usbh_dev_t *hw)
{
return hw->hprt_reg.prtena;
}
static inline void usbh_ll_hprt_port_dis(usbh_dev_t *hw)
{
usb_hprt_reg_t hprt;
hprt.val = hw->hprt_reg.val;
hprt.prtena = 1; //W1C to disable
//we want to W1C ENA but not W1C the interrupt bits
hw->hprt_reg.val = hprt.val & ((~USBH_LL_HPRT_W1C_MSK) | USBH_LL_HPRT_ENA_MSK);
}
static inline bool usbh_ll_hprt_get_conn_status(usbh_dev_t *hw)
{
return hw->hprt_reg.prtconnsts;
}
static inline uint32_t usbh_ll_hprt_intr_read_and_clear(usbh_dev_t *hw)
{
usb_hprt_reg_t hprt;
hprt.val = hw->hprt_reg.val;
//We want to W1C the interrupt bits but not that ENA
hw->hprt_reg.val = hprt.val & (~USBH_LL_HPRT_ENA_MSK);
//Return only the interrupt bits
return (hprt.val & (USBH_LL_HPRT_W1C_MSK & ~(USBH_LL_HPRT_ENA_MSK)));
}
//Per Channel registers
// --------------------------- HCCHARi Register --------------------------------
static inline void usbh_ll_chan_start(volatile usb_host_chan_regs_t *chan)
{
chan->hcchar_reg.chena = 1;
}
static inline bool usbh_ll_chan_is_active(volatile usb_host_chan_regs_t *chan)
{
return chan->hcchar_reg.chena;
}
static inline void usbh_ll_chan_halt(volatile usb_host_chan_regs_t *chan)
{
chan->hcchar_reg.chdis = 1;
}
static inline void usbh_ll_chan_xfer_odd_frame(volatile usb_host_chan_regs_t *chan)
{
chan->hcchar_reg.oddfrm = 1;
}
static inline void usbh_ll_chan_xfer_even_frame(volatile usb_host_chan_regs_t *chan)
{
chan->hcchar_reg.oddfrm = 0;
}
static inline void usbh_ll_chan_set_dev_addr(volatile usb_host_chan_regs_t *chan, uint32_t addr)
{
chan->hcchar_reg.devaddr = addr;
}
static inline void usbh_ll_chan_set_ep_type(volatile usb_host_chan_regs_t *chan, usb_xfer_type_t type)
{
switch (type) {
case USB_XFER_TYPE_CTRL:
chan->hcchar_reg.eptype = 0x0;
break;
case USB_XFER_TYPE_ISOCHRONOUS:
chan->hcchar_reg.eptype = 0x1;
break;
case USB_XFER_TYPE_BULK:
chan->hcchar_reg.eptype = 0x2;
break;
case USB_XFER_TYPE_INTR:
chan->hcchar_reg.eptype = 0x3;
break;
default:
;
}
}
static inline void usbh_ll_chan_set_ls(volatile usb_host_chan_regs_t *chan)
{
chan->hcchar_reg.lspddev = 1;
}
static inline void usbh_ll_chan_set_dir(volatile usb_host_chan_regs_t *chan, bool is_in)
{
chan->hcchar_reg.epdir = is_in;
}
static inline void usbh_ll_chan_set_ep_num(volatile usb_host_chan_regs_t *chan, uint32_t num)
{
chan->hcchar_reg.epnum = num;
}
static inline void usbh_ll_chan_set_mps(volatile usb_host_chan_regs_t *chan, uint32_t mps)
{
chan->hcchar_reg.mps = mps;
}
static inline void usbh_ll_chan_hcchar_init(volatile usb_host_chan_regs_t *chan, int dev_addr, int ep_num, int mps, usb_xfer_type_t type, bool is_in)
{
//Sets all persistent fields of the channel over its lifetime
usbh_ll_chan_set_dev_addr(chan, dev_addr);
usbh_ll_chan_set_ep_type(chan, type);
usbh_ll_chan_set_dir(chan, is_in);
usbh_ll_chan_set_ep_num(chan, ep_num);
usbh_ll_chan_set_mps(chan, mps);
}
// ---------------------------- HCINTi Register --------------------------------
static inline uint32_t usbh_ll_chan_intr_read_and_clear(volatile usb_host_chan_regs_t *chan)
{
usb_hcint_reg_t hcint;
hcint.val = chan->hcint_reg.val;
chan->hcint_reg.val = hcint.val;
return hcint.val;
}
// --------------------------- HCINTMSKi Register ------------------------------
static inline void usbh_ll_chan_set_intr_mask(volatile usb_host_chan_regs_t *chan, uint32_t mask)
{
chan->hcintmsk_reg.val = mask;
}
// ---------------------- HCTSIZi and HCDMAi Registers -------------------------
static inline void usbh_ll_chan_set_pid(volatile usb_host_chan_regs_t *chan, uint32_t data_pid)
{
if (data_pid == 0) {
chan->hctsiz_reg.pid = 0;
} else {
chan->hctsiz_reg.pid = 2;
}
}
static inline void usbh_ll_chan_set_dma_addr_non_iso(volatile usb_host_chan_regs_t *chan,
void *dmaaddr,
uint32_t qtd_idx)
{
//Set HCDMAi
chan->hcdma_reg.val = 0;
chan->hcdma_reg.non_iso.dmaaddr = (((uint32_t)dmaaddr) >> 9) & 0x7FFFFF; //MSB of 512 byte aligned address
chan->hcdma_reg.non_iso.ctd = qtd_idx;
}
static inline void usbh_ll_chan_set_dma_addr_iso(volatile usb_host_chan_regs_t *chan,
void *dmaaddr,
uint32_t ntd,
uint32_t pktcnt,
uint32_t ctd)
{
int n;
if (ntd == 2) {
n = 4;
} else if (ntd == 4) {
n = 5;
} else if (ntd == 8) {
n = 6;
} else if (ntd == 16) {
n = 7;
} else if (ntd == 32) {
n = 8;
} else { //ntd == 64
n = 9;
}
//Set HCTSIZi
chan->hctsiz_reg.ntd = ntd -1;
chan->hctsiz_reg.sched_info = 0xFF; //Always set to 0xFF for FS
//Set HCDMAi
chan->hcdma_reg.iso.dmaaddr_ctd = (((uint32_t)dmaaddr) & 0x1FF) << (n-3); //ctd is set to 0
}
static inline int usbh_ll_chan_get_ctd(usb_host_chan_regs_t *chan)
{
return chan->hcdma_reg.non_iso.ctd;
}
static inline void usbh_ll_chan_hctsiz_init(volatile usb_host_chan_regs_t *chan, int qtd_list_len)
{
//HCTSIZi
chan->hctsiz_reg.dopng = 0; //Don't do ping
chan->hctsiz_reg.pid = 0; //Reset PID to Data0
chan->hctsiz_reg.ntd = qtd_list_len - 1; //Set the length of the descriptor list
chan->hctsiz_reg.sched_info = 0xFF; //Schedinfo is always 0xFF for fullspeed. Not used in Bulk/Ctrl channels
}
// ---------------------------- HCDMABi Register -------------------------------
static inline void *usbh_ll_chan_get_cur_buff_addr(volatile usb_host_chan_regs_t *chan)
{
return (void *)chan->hcdmab_reg.hcdmab;
}
/* -----------------------------------------------------------------------------
---------------------------- Scatter/Gather DMA QTDs ---------------------------
----------------------------------------------------------------------------- */
// ---------------------------- Helper Functions -------------------------------
/**
* @brief Get the base address of a channel's register based on the channel's index
*
* @param dev Start address of the DWC_OTG registers
* @param chan_idx The channel's index
* @return usb_host_chan_regs_t* Pointer to channel's registers
*/
static inline usb_host_chan_regs_t *usbh_ll_get_chan_regs(usbh_dev_t *dev, int chan_idx)
{
return &dev->host_chans[chan_idx];
}
// ------------------------------ QTD related ----------------------------------
#define USBH_LL_QTD_STATUS_SUCCESS 0x0 //If QTD was processed, it indicates the data was transmitted/received successfully
#define USBH_LL_QTD_STATUS_PKTERR 0x1 //Data trasnmitted/received with errors (CRC/Timeout/Stuff/False EOP/Excessive NAK).
//Note: 0x2 is reserved
#define USBH_LL_QTD_STATUS_BUFFER 0x3 //AHB error occurred.
#define USBH_LL_QTD_STATUS_NOT_EXECUTED 0x4 //QTD as never processed
/**
* @brief Set a QTD for a non isochronous IN transfer
*
* @param qtd Pointer to the QTD
* @param data_buff Pointer to buffer containing the data to transfer
* @param xfer_len Number of bytes in transfer. Setting 0 will do a zero length IN transfer.
* Non zero length must be mulitple of the endpoint's MPS.
* @param halt_on_cplt Generate a channel halted interrupt on completion of QTD
*/
static inline void usbh_ll_set_qtd_in(usbh_ll_dma_qtd_t *qtd, void *data_buff, int xfer_len, bool halt_on_cplt)
{
qtd->buffer = data_buff; //Set pointer to data buffer
qtd->buffer_status_val = 0; //Reset all flags to zero
qtd->in_non_iso.xfer_size = xfer_len;
if (halt_on_cplt) {
qtd->in_non_iso.intr_cplt = 1; //Used to indicate successful completion
qtd->in_non_iso.eol = 1; //Used to halt the channel at this qtd
}
qtd->in_non_iso.active = 1;
}
/**
* @brief Set a QTD for a non isochronous OUT transfer
*
* @param qtd Poitner to the QTD
* @param data_buff Pointer to buffer containing the data to transfer
* @param xfer_len Number of bytes to transfer. Setting 0 will do a zero length transfer.
* For ctrl setup packets, this should be set to 8.
* @param halt_on_cplt Generate a channel halted interrupt on completion of QTD.
* @param is_setup Indicates whether this is a control transfer setup packet or a normal OUT Data transfer.
* (As per the USB protocol, setup packets cannot be STALLd or NAKd by the device)
*/
static inline void usbh_ll_set_qtd_out(usbh_ll_dma_qtd_t *qtd, void *data_buff, int xfer_len, bool halt_on_cplt, bool is_setup)
{
qtd->buffer = data_buff; //Set pointer to data buffer
qtd->buffer_status_val = 0; //Reset all flags to zero
qtd->out_non_iso.xfer_size = xfer_len;
if (is_setup) {
qtd->out_non_iso.is_setup = 1;
}
if (halt_on_cplt) {
qtd->out_non_iso.intr_cplt = 1; //Used to indicate successful completion
qtd->out_non_iso.eol = 1; //Used to halt the channel at this qtd
}
qtd->out_non_iso.active = 1;
}
/**
* @brief Set a QTD as NULL
*
* This sets the QTD to a value of 0. This is only useful when you need to insert
* blank QTDs into a list of QTDs
*
* @param qtd Pointer to the QTD
*/
static inline void usbh_ll_set_qtd_null(usbh_ll_dma_qtd_t *qtd)
{
qtd->buffer = NULL;
qtd->buffer_status_val = 0; //Disable qtd by clearing it to zero. Used by interrupt/isoc as an unscheudled frame
}
/**
* @brief Get the status of a QTD
*
* When a channel get's halted, call this to check whether each QTD was executed successfully
*
* @param qtd Poitner to the QTD
* @param[out] rem_len Number of bytes ramining in the QTD
* @param[out] status Status of the QTD
*/
static inline void usbh_ll_get_qtd_status(usbh_ll_dma_qtd_t *qtd, int *rem_len, int *status)
{
//Status is the same regardless of IN or OUT
if (qtd->in_non_iso.active) {
//QTD was never processed
*status = USBH_LL_QTD_STATUS_NOT_EXECUTED;
} else {
*status = qtd->in_non_iso.rx_status;
}
*rem_len = qtd->in_non_iso.xfer_size;
//Clear the QTD just for safety
qtd->buffer_status_val = 0;
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,394 @@
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#define USB_CTRL_REQ_ATTR __attribute__((packed))
#define USB_DESC_ATTR __attribute__((packed))
/* -----------------------------------------------------------------------------
------------------------------ USB Protocol Enums ------------------------------
----------------------------------------------------------------------------- */
/**
* @brief Enumeration of USB PHY type
*/
typedef enum {
USB_PHY_INTERNAL = 0, /**< Use the chip's internal USB PHY */
USB_PHY_EXTERNAL, /**< Use an external USB PHY */
} usb_phy_t;
/**
* @brief The type of USB transfer
*
* @note The enum values need to match the bmAttributes field of an EP descriptor
*/
typedef enum {
USB_XFER_TYPE_CTRL = 0,
USB_XFER_TYPE_ISOCHRONOUS,
USB_XFER_TYPE_BULK,
USB_XFER_TYPE_INTR,
} usb_xfer_type_t;
/**
* @brief USB Standard Speeds
*/
typedef enum {
USB_SPEED_LOW = 0, /**< USB Low Speed (1.5 Mbit/s) */
USB_SPEED_FULL, /**< USB Full Speed (12 Mbit/s) */
} usb_speed_t;
/* -----------------------------------------------------------------------------
-------------------------------- Control Request -------------------------------
----------------------------------------------------------------------------- */
/**
* @brief Size of a USB control transfer setup packet in bytes
*/
#define USB_CTRL_REQ_SIZE 8
/**
* @brief Structure representing a USB control transfer setup packet
*/
typedef union {
struct {
uint8_t bRequestType;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
} USB_CTRL_REQ_ATTR;
uint8_t val[USB_CTRL_REQ_SIZE];
} usb_ctrl_req_t;
_Static_assert(sizeof(usb_ctrl_req_t) == USB_CTRL_REQ_SIZE, "Size of usb_ctrl_req_t incorrect");
/**
* @brief Bit masks pertaining to the bRequestType field of a setup packet
*/
#define USB_B_REQUEST_TYPE_DIR_OUT (0X00 << 7)
#define USB_B_REQUEST_TYPE_DIR_IN (0x01 << 7)
#define USB_B_REQUEST_TYPE_TYPE_STANDARD (0x00 << 5)
#define USB_B_REQUEST_TYPE_TYPE_CLASS (0x01 << 5)
#define USB_B_REQUEST_TYPE_TYPE_VENDOR (0x02 << 5)
#define USB_B_REQUEST_TYPE_TYPE_RESERVED (0x03 << 5)
#define USB_B_REQUEST_TYPE_TYPE_MASK (0x03 << 5)
#define USB_B_REQUEST_TYPE_RECIP_DEVICE (0x00 << 0)
#define USB_B_REQUEST_TYPE_RECIP_INTERFACE (0x01 << 0)
#define USB_B_REQUEST_TYPE_RECIP_ENDPOINT (0x02 << 0)
#define USB_B_REQUEST_TYPE_RECIP_OTHER (0x03 << 0)
#define USB_B_REQUEST_TYPE_RECIP_MASK (0x1f << 0)
/**
* @brief Bit masks pertaining to the bRequest field of a setup packet
*/
#define USB_B_REQUEST_GET_STATUS 0x00
#define USB_B_REQUEST_CLEAR_FEATURE 0x01
#define USB_B_REQUEST_SET_FEATURE 0x03
#define USB_B_REQUEST_SET_ADDRESS 0x05
#define USB_B_REQUEST_GET_DESCRIPTOR 0x06
#define USB_B_REQUEST_SET_DESCRIPTOR 0x07
#define USB_B_REQUEST_GET_CONFIGURATION 0x08
#define USB_B_REQUEST_SET_CONFIGURATION 0x09
#define USB_B_REQUEST_GET_INTERFACE 0x0A
#define USB_B_REQUEST_SET_INTERFACE 0x0B
#define USB_B_REQUEST_SYNCH_FRAME 0x0C
/**
* @brief Bit masks pertaining to the wValue field of a setup packet
*/
#define USB_W_VALUE_DT_DEVICE 0x01
#define USB_W_VALUE_DT_CONFIG 0x02
#define USB_W_VALUE_DT_STRING 0x03
#define USB_W_VALUE_DT_INTERFACE 0x04
#define USB_W_VALUE_DT_ENDPOINT 0x05
#define USB_W_VALUE_DT_DEVICE_QUALIFIER 0x06
#define USB_W_VALUE_DT_OTHER_SPEED_CONFIG 0x07
#define USB_W_VALUE_DT_INTERFACE_POWER 0x08
/**
* @brief Initializer for a SET_ADDRESS request
*
* Sets the address of a connected device
*/
#define USB_CTRL_REQ_INIT_SET_ADDR(ctrl_req_ptr, addr) ({ \
(ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_OUT | USB_B_REQUEST_TYPE_TYPE_STANDARD |USB_B_REQUEST_TYPE_RECIP_DEVICE; \
(ctrl_req_ptr)->bRequest = USB_B_REQUEST_SET_ADDRESS; \
(ctrl_req_ptr)->wValue = (addr); \
(ctrl_req_ptr)->wIndex = 0; \
(ctrl_req_ptr)->wLength = 0; \
})
/**
* @brief Initializer for a request to get a device's device descriptor
*/
#define USB_CTRL_REQ_INIT_GET_DEVC_DESC(ctrl_req_ptr) ({ \
(ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_IN | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_DEVICE; \
(ctrl_req_ptr)->bRequest = USB_B_REQUEST_GET_DESCRIPTOR; \
(ctrl_req_ptr)->wValue = (USB_W_VALUE_DT_DEVICE << 8); \
(ctrl_req_ptr)->wIndex = 0; \
(ctrl_req_ptr)->wLength = 18; \
})
/**
* @brief Initializer for a request to get a device's current configuration number
*/
#define USB_CTRL_REQ_INIT_GET_CONFIG(ctrl_req_ptr) ({ \
(ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_IN | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_DEVICE; \
(ctrl_req_ptr)->bRequest = USB_B_REQUEST_GET_CONFIGURATION; \
(ctrl_req_ptr)->wValue = 0; \
(ctrl_req_ptr)->wIndex = 0; \
(ctrl_req_ptr)->wLength = 1; \
})
/**
* @brief Initializer for a request to get one of the device's current configuration descriptor
*
* - desc_index indicates the configuration's index number
* - Number of bytes of the configuration descriptor to get
*/
#define USB_CTRL_REQ_INIT_GET_CFG_DESC(ctrl_req_ptr, desc_index, desc_len) ({ \
(ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_IN | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_DEVICE; \
(ctrl_req_ptr)->bRequest = USB_B_REQUEST_GET_DESCRIPTOR; \
(ctrl_req_ptr)->wValue = (USB_W_VALUE_DT_CONFIG << 8) | ((desc_index) & 0xFF); \
(ctrl_req_ptr)->wIndex = 0; \
(ctrl_req_ptr)->wLength = (desc_len); \
})
/**
* @brief Initializer for a request to set a device's current configuration number
*/
#define USB_CTRL_REQ_INIT_SET_CONFIG(ctrl_req_ptr, config_num) ({ \
(ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_OUT | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_DEVICE; \
(ctrl_req_ptr)->bRequest = USB_B_REQUEST_SET_CONFIGURATION; \
(ctrl_req_ptr)->wValue = (config_num); \
(ctrl_req_ptr)->wIndex = 0; \
(ctrl_req_ptr)->wLength = 0; \
})
/* -----------------------------------------------------------------------------
---------------------------------- Descriptors ---------------------------------
----------------------------------------------------------------------------- */
// -------------------------- Device Descriptor --------------------------------
/**
* @brief Size of a USB device descriptor in bytes
*/
#define USB_DESC_DEV_SIZE 18
/**
* @brief Structure representing a USB device descriptor
*/
typedef union {
struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdUSB;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize0;
uint16_t idVendor;
uint16_t idProduct;
uint16_t bcdDevice;
uint8_t iManufacturer;
uint8_t iProduct;
uint8_t iSerialNumber;
uint8_t bNumConfigurations;
} USB_DESC_ATTR;
uint8_t val[USB_DESC_DEV_SIZE];
} usb_desc_devc_t;
_Static_assert(sizeof(usb_desc_devc_t) == USB_DESC_DEV_SIZE, "Size of usb_desc_devc_t incorrect");
/**
* @brief Possible base class values of the bDeviceClass field of a USB device descriptor
*/
#define USB_CLASS_PER_INTERFACE 0x00
#define USB_CLASS_AUDIO 0x01
#define USB_CLASS_COMM 0x02
#define USB_CLASS_HID 0x03
#define USB_CLASS_PHYSICAL 0x05
#define USB_CLASS_STILL_IMAGE 0x06
#define USB_CLASS_PRINTER 0x07
#define USB_CLASS_MASS_STORAGE 0x08
#define USB_CLASS_HUB 0x09
#define USB_CLASS_CDC_DATA 0x0a
#define USB_CLASS_CSCID 0x0b
#define USB_CLASS_CONTENT_SEC 0x0d
#define USB_CLASS_VIDEO 0x0e
#define USB_CLASS_WIRELESS_CONTROLLER 0xe0
#define USB_CLASS_PERSONAL_HEALTHCARE 0x0f
#define USB_CLASS_AUDIO_VIDEO 0x10
#define USB_CLASS_BILLBOARD 0x11
#define USB_CLASS_USB_TYPE_C_BRIDGE 0x12
#define USB_CLASS_MISC 0xef
#define USB_CLASS_APP_SPEC 0xfe
#define USB_CLASS_VENDOR_SPEC 0xff
/**
* @brief Vendor specific subclass code
*/
#define USB_SUBCLASS_VENDOR_SPEC 0xff
// ----------------------- Configuration Descriptor ----------------------------
/**
* @brief Size of a short USB configuration descriptor in bytes
*
* @note The size of a full USB configuration includes all the interface and endpoint
* descriptors of that configuration.
*/
#define USB_DESC_CFG_SIZE 9
/**
* @brief Structure representing a short USB configuration descriptor
*
* @note The full USB configuration includes all the interface and endpoint
* descriptors of that configuration.
*/
typedef union {
struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wTotalLength;
uint8_t bNumInterfaces;
uint8_t bConfigurationValue;
uint8_t iConfiguration;
uint8_t bmAttributes;
uint8_t bMaxPower;
} USB_DESC_ATTR;
uint8_t val[USB_DESC_CFG_SIZE];
} usb_desc_cfg_t;
_Static_assert(sizeof(usb_desc_cfg_t) == USB_DESC_CFG_SIZE, "Size of usb_desc_cfg_t incorrect");
/**
* @brief Bit masks pertaining to the bmAttributes field of a configuration descriptor
*/
#define USB_BM_ATTRIBUTES_ONE (1 << 7) //Must be set
#define USB_BM_ATTRIBUTES_SELFPOWER (1 << 6) //Self powered
#define USB_BM_ATTRIBUTES_WAKEUP (1 << 5) //Can wakeup
#define USB_BM_ATTRIBUTES_BATTERY (1 << 4) //Battery powered
// ------------------------- Interface Descriptor ------------------------------
/**
* @brief Size of a USB interface descriptor in bytes
*/
#define USB_DESC_INTF_SIZE 9
/**
* @brief Structure representing a USB interface descriptor
*/
typedef union {
struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting;
uint8_t bNumEndpoints;
uint8_t bInterfaceClass;
uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol;
uint8_t iInterface;
} USB_DESC_ATTR;
uint8_t val[USB_DESC_INTF_SIZE];
} usb_desc_intf_t;
_Static_assert(sizeof(usb_desc_intf_t) == USB_DESC_INTF_SIZE, "Size of usb_desc_intf_t incorrect");
// ------------------------- Endpoint Descriptor -------------------------------
/**
* @brief Size of a USB endpoint descriptor in bytes
*/
#define USB_DESC_EP_SIZE 7
/**
* @brief Structure representing a USB endp;oint descriptor
*/
typedef union {
struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint16_t wMaxPacketSize;
uint8_t bInterval;
} USB_DESC_ATTR;
uint8_t val[USB_DESC_EP_SIZE];
} usb_desc_ep_t;
_Static_assert(sizeof(usb_desc_ep_t) == USB_DESC_EP_SIZE, "Size of usb_desc_ep_t incorrect");
/**
* @brief Bit masks pertaining to the bEndpointAddress field of an endpoint descriptor
*/
#define USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK 0x0f
#define USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK 0x80
/**
* @brief Bit masks pertaining to the bmAttributes field of an endpoint descriptor
*/
#define USB_BM_ATTRIBUTES_XFERTYPE_MASK 0x03
#define USB_BM_ATTRIBUTES_XFER_CONTROL (0 << 0)
#define USB_BM_ATTRIBUTES_XFER_ISOC (1 << 0)
#define USB_BM_ATTRIBUTES_XFER_BULK (2 << 0)
#define USB_BM_ATTRIBUTES_XFER_INT (3 << 0)
#define USB_BM_ATTRIBUTES_SYNCTYPE_MASK 0x0C /* in bmAttributes */
#define USB_BM_ATTRIBUTES_SYNC_NONE (0 << 2)
#define USB_BM_ATTRIBUTES_SYNC_ASYNC (1 << 2)
#define USB_BM_ATTRIBUTES_SYNC_ADAPTIVE (2 << 2)
#define USB_BM_ATTRIBUTES_SYNC_SYNC (3 << 2)
#define USB_BM_ATTRIBUTES_USAGETYPE_MASK 0x30
#define USB_BM_ATTRIBUTES_USAGE_DATA (0 << 4)
#define USB_BM_ATTRIBUTES_USAGE_FEEDBACK (1 << 4)
#define USB_BM_ATTRIBUTES_USAGE_IMPLICIT_FB (2 << 4)
/**
* @brief Macro helpers to get information about an endpoint from its descriptor
*/
#define USB_DESC_EP_GET_XFERTYPE(desc_ptr) ((usb_xfer_type_t) ((desc_ptr)->bmAttributes & USB_BM_ATTRIBUTES_XFERTYPE_MASK))
#define USB_DESC_EP_GET_EP_NUM(desc_ptr) ((desc_ptr)->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK)
#define USB_DESC_EP_GET_EP_DIR(desc_ptr) (((desc_ptr)->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK) ? 1 : 0)
#define USB_DESC_EP_GET_MPS(desc_ptr) ((desc_ptr)->wMaxPacketSize & 0x7FF)
// --------------------------- String Descriptor -------------------------------
/**
* @brief Size of a short USB string descriptor in bytes
*/
#define USB_DESC_STR_SIZE 4
/**
* @brief Structure representing a USB string descriptor
*/
typedef union {
struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wData[1]; /* UTF-16LE encoded */
} USB_DESC_ATTR;
uint8_t val[USB_DESC_STR_SIZE];
} usb_desc_str_t;
_Static_assert(sizeof(usb_desc_str_t) == USB_DESC_STR_SIZE, "Size of usb_desc_str_t incorrect");
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load Diff