mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-01 03:34:32 +02:00
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:
@@ -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 );
|
||||
|
886
components/hal/esp32s2/include/hal/usbh_ll.h
Normal file
886
components/hal/esp32s2/include/hal/usbh_ll.h
Normal 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
|
394
components/hal/include/hal/usb_types.h
Normal file
394
components/hal/include/hal/usb_types.h
Normal 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
|
1163
components/soc/esp32s2/include/soc/usbh_struct.h
Normal file
1163
components/soc/esp32s2/include/soc/usbh_struct.h
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user