Răsfoiți Sursa

esp_rom: add USB related headers from the ROM code

Ivan Grokhotkov 5 ani în urmă
părinte
comite
4901917ea3

+ 6 - 1
components/esp_rom/esp32s2/ld/esp32s2.rom.ld

@@ -570,6 +570,11 @@ PROVIDE ( rom_txiq_set_reg = 0x4000bf64 );
 PROVIDE ( rom_tx_paon_set = 0x40009db8 );
 PROVIDE ( rom_tx_pwr_backoff = 0x4000ceb8 );
 PROVIDE ( rom_txtone_linear_pwr = 0x4000c0b0 );
+PROVIDE ( rom_usb_dev = 0x3ffffb9c );  /* static "usb_dev" */
+PROVIDE ( rom_usb_dev_end = 0x3ffffc78 );  /* end of "usb_dev" */
+PROVIDE ( rom_usb_dw_ctrl = 0x3ffffa74 );  /* static "usb_dw_ctrl" */
+PROVIDE ( rom_usb_dw_ctrl_end = 0x3ffffb9c );  /* end of "usb_dw_ctrl" */
+PROVIDE ( rom_usb_curr_desc = 0x3ffffa54 ); /* static "s_curr_descr" */
 PROVIDE ( rom_wait_rfpll_cal_end = 0x4000af3c );
 PROVIDE ( rom_wifi_11g_rate_chg = 0x4000d260 );
 PROVIDE ( rom_wifi_rifs_mode_en = 0x40009d2c );
@@ -646,7 +651,7 @@ PROVIDE ( string0_descr = 0x3ffaeeae );
 PROVIDE ( str_manu_descr = 0x3ffaee9a );
 PROVIDE ( str_prod_descr = 0x3ffaee88 );
 PROVIDE ( str_serial_descr = 0x3ffaee84 );
-PROVIDE ( s_usb_osglue = 0x3ffffcdc );
+PROVIDE ( rom_usb_osglue = 0x3ffffcdc );
 PROVIDE ( _SyscallException = 0x4000732a );
 PROVIDE ( syscall_table_ptr_pro = 0x3ffffd78 );
 PROVIDE ( tdefl_compress = 0x400041dc );

+ 10 - 1
components/esp_rom/include/esp32s2/rom/uart.h

@@ -162,6 +162,14 @@ typedef struct {
     int              received;
 } UartDevice;
 
+typedef enum {
+    ROM_UART_0,
+    ROM_UART_1,
+    ROM_UART_USB
+} rom_uart_num_t;
+
+#define CDC_ACM_WORK_BUF_MIN 128
+
 /**
   * @brief Init uart device struct value and reset uart0/uart1 rx.
   *        Please do not call this function in SDK.
@@ -428,7 +436,8 @@ uint8_t UartConnCheck(uint8_t uart_no);
 
 /**
   * @brief Initialize the USB ACM UART
-  * Needs to be fed a buffer of at least 128 bytes, plus any rx buffer you may want to have.
+  * Needs to be fed a buffer of at least 128 bytes (CDC_ACM_WORK_BUF_MIN),
+  * plus any rx buffer you may want to have.
   *
   * @param cdc_acm_work_mem Pointer to work mem for CDC-ACM code
   * @param cdc_acm_work_mem_len Length of work mem

+ 262 - 0
components/esp_rom/include/esp32s2/rom/usb/cdc_acm.h

@@ -0,0 +1,262 @@
+/*******************************************************************************
+ *
+ * Copyright(c) 2015,2016 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************/
+
+#pragma once
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void cdc_acm_device;
+extern cdc_acm_device *uart_acm_dev;
+
+#define ACM_BYTES_PER_TX  64
+
+//ACM statuses are negative to distinguish from USB_DC_* status codes
+#define ACM_STATUS_LINESTATE_CHANGED -1
+#define ACM_STATUS_LINECODING_CHANGED -2
+#define ACM_STATUS_TX -3
+#define ACM_STATUS_RX -4
+
+typedef void(*uart_irq_callback_t)(cdc_acm_device *dev, int status);
+
+/**
+ * @brief Get amount of received characters in buffer
+ *
+ * @returns character count
+ */
+
+int cdc_acm_rx_fifo_cnt(cdc_acm_device *dev);
+
+
+/*
+ * @brief Poll the device for input.
+ *
+ * @return -ENOTSUP Since underlying USB device controller always uses
+ * interrupts, polled mode UART APIs are not implemented for the UART interface
+ * exported by CDC ACM driver. Apps should use fifo_read API instead.
+ */
+
+int cdc_acm_poll_in(cdc_acm_device *dev, unsigned char *c);
+
+/*
+ * @brief Output a character in polled mode.
+ *
+ * The UART poll method for USB UART is simulated by waiting till
+ * we get the next BULK In upcall from the USB device controller or 100 ms.
+ *
+ * @return the same character which is sent
+ */
+unsigned char cdc_acm_poll_out(cdc_acm_device *dev, unsigned char c);
+
+/**
+ * @brief Fill FIFO with data
+ *
+ * @param dev     CDC ACM device struct.
+ * @param tx_data Data to transmit.
+ * @param len     Number of bytes to send.
+ *
+ * @return Number of bytes sent.
+ */
+int cdc_acm_fifo_fill(cdc_acm_device *dev, const uint8_t *tx_data, int len);
+
+/**
+ * @brief Read data from FIFO
+ *
+ * @param dev     CDC ACM device struct.
+ * @param rx_data Pointer to data container.
+ * @param size    Container size.
+ *
+ * @return Number of bytes read.
+ */
+int cdc_acm_fifo_read(cdc_acm_device *dev, uint8_t *rx_data, const int size);
+
+/**
+ * @brief Enable TX interrupt
+ *
+ * @param dev CDC ACM device struct.
+ *
+ * @return N/A.
+ */
+void cdc_acm_irq_tx_enable(cdc_acm_device *dev);
+
+/**
+ * @brief Disable TX interrupt
+ *
+ * @param dev CDC ACM device struct.
+ *
+ * @return N/A.
+ */
+void cdc_acm_irq_tx_disable(cdc_acm_device *dev);
+
+/**
+ * @brief Check if Tx IRQ has been raised
+ *
+ * @param dev CDC ACM device struct.
+ *
+ * @return 1 if a Tx IRQ is pending, 0 otherwise.
+ */
+int cdc_acm_irq_tx_ready(cdc_acm_device *dev);
+
+/**
+ * @brief Enable RX interrupt
+ *
+ * @param dev CDC ACM device struct.
+ *
+ * @return N/A
+ */
+void cdc_acm_irq_rx_enable(cdc_acm_device *dev);
+
+/**
+ * @brief Disable RX interrupt
+ *
+ * @param dev CDC ACM device struct.
+ *
+ * @return N/A.
+ */
+void cdc_acm_irq_rx_disable(cdc_acm_device *dev);
+
+/**
+ * @brief Enable line state interrupt
+ *
+ * @param dev CDC ACM device struct.
+ *
+ * @return N/A.
+ */
+void cdc_acm_irq_state_enable(cdc_acm_device *dev);
+
+/**
+ * @brief Disable line state interrupt
+ *
+ * @param dev CDC ACM device struct.
+ *
+ * @return N/A.
+ */
+void cdc_acm_irq_state_disable(cdc_acm_device *dev);
+
+
+/**
+ * @brief Check if Rx IRQ has been raised
+ *
+ * @param dev CDC ACM device struct.
+ *
+ * @return 1 if an IRQ is ready, 0 otherwise.
+ */
+int cdc_acm_irq_rx_ready(cdc_acm_device *dev);
+
+/**
+ * @brief Check if Tx or Rx IRQ is pending
+ *
+ * @param dev CDC ACM device struct.
+ *
+ * @return 1 if a Tx or Rx IRQ is pending, 0 otherwise.
+ */
+int cdc_acm_irq_is_pending(cdc_acm_device *dev);
+
+/**
+ * @brief Set the callback function pointer for IRQ.
+ *
+ * @param dev CDC ACM device struct.
+ * @param cb  Callback function pointer.
+ *
+ * @return N/A
+ */
+void cdc_acm_irq_callback_set(cdc_acm_device *dev, uart_irq_callback_t cb);
+
+/**
+ * @brief Manipulate line control for UART.
+ *
+ * @param dev CDC ACM device struct
+ * @param ctrl The line control to be manipulated
+ * @param val Value to set the line control
+ *
+ * @return 0 if successful, failed otherwise.
+ */
+int cdc_acm_line_ctrl_set(cdc_acm_device *dev, uint32_t ctrl, uint32_t val);
+
+/**
+ * @brief Manipulate line control for UART.
+ *
+ * @param dev CDC ACM device struct
+ * @param ctrl The line control to be manipulated
+ * @param val Value to set the line control
+ *
+ * @return 0 if successful, failed otherwise.
+ */
+int cdc_acm_line_ctrl_get(cdc_acm_device *dev, uint32_t ctrl, uint32_t *val);
+
+
+/**
+ * @brief Initialize UART channel
+ *
+ * This routine is called to reset the chip in a quiescent state.
+ * It is assumed that this function is called only once per UART.
+ *
+ * @param mem_chunk Memory chunk to use for internal use
+ * @param mem_chunk_size Size of the memory chunk in bytes
+ *
+ * @return dev or NULL
+ */
+cdc_acm_device *cdc_acm_init(void *mem_chunk, int mem_chunk_size);
+
+
+/** Common line controls for UART.*/
+#define LINE_CTRL_BAUD_RATE (1 << 0)
+#define LINE_CTRL_RTS       (1 << 1)
+#define LINE_CTRL_DTR       (1 << 2)
+#define LINE_CTRL_DCD       (1 << 3)
+#define LINE_CTRL_DSR       (1 << 4)
+
+/* Common communication errors for UART.*/
+
+/** @brief Overrun error */
+#define UART_ERROR_OVERRUN  (1 << 0)
+
+/** @brief Parity error */
+#define UART_ERROR_PARITY   (1 << 1)
+
+/** @brief Framing error */
+#define UART_ERROR_FRAMING  (1 << 2)
+
+/**
+ * @brief Break interrupt error:
+ *
+ * A break interrupt was received. This happens when the serial input is
+ * held at a logic '0' state for longer than the sum of start time + data bits
+ * + parity + stop bits.
+ */
+#define UART_ERROR_BREAK    (1 << 3)
+
+#ifdef __cplusplus
+}
+#endif

+ 30 - 0
components/esp_rom/include/esp32s2/rom/usb/chip_usb_dw_wrapper.h

@@ -0,0 +1,30 @@
+// Copyright 2019-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
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int chip_usb_dw_init(void);
+int chip_usb_dw_did_persist(void);
+void chip_usb_dw_prepare_persist(void);
+uint32_t chip_usb_get_persist_flags(void);
+void chip_usb_set_persist_flags(uint32_t flags);
+
+#ifdef __cplusplus
+}
+#endif

+ 180 - 0
components/esp_rom/include/esp32s2/rom/usb/cpio.h

@@ -0,0 +1,180 @@
+// Copyright 2015-2016 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.
+
+
+/**
+ * Archive to parse cpio data in the newc and crc formats. Generate a cpio archive like that by e.g.
+ * find . | cpio -o -H newc > archive.cpio
+ */
+
+#pragma once
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CPIO_MODE_FILETYPE_MASK     0xF000
+#define CPIO_MODE_FILETYPE_SOCKET   0xC000
+#define CPIO_MODE_FILETYPE_SYMLINK  0xA000
+#define CPIO_MODE_FILETYPE_REGULAR  0x8000
+#define CPIO_MODE_FILETYPE_BLOCKDEV 0x6000
+#define CPIO_MODE_FILETYPE_DIR      0x4000
+#define CPIO_MODE_FILETYPE_CHARDEV  0x2000
+#define CPIO_MODE_FILETYPE_FIFO     0x1000
+#define CPIO_MODE_SUID              0x0800
+#define CPIO_MODE_SGID              0x0400
+#define CPIO_MODE_STICKY            0x0200
+
+typedef struct {
+    size_t filesize;
+    char *name;
+    uint32_t mode;
+    uint32_t check;
+} cpio_file_t;
+
+typedef enum {
+    CPIO_RET_MORE = 0,
+    CPIO_RET_DONE,
+    CPIO_RET_ERR
+} cpio_ret_t;
+
+typedef struct cpio_handle_data_t cpio_handle_data_t;
+typedef cpio_handle_data_t *cpio_handle_t;
+
+typedef enum {
+    CPIO_RSN_FILE_ALL = 0,
+    CPIO_RSN_FILE_INITIAL,
+    CPIO_RSN_FILE_MORE,
+    CPIO_RSN_FILE_END
+} cpio_callback_reason_t;
+
+
+/**
+ * Callback for cpio file data.
+ *
+ * This callback will be called by the library to indicate data for a file is available.
+ *
+ * For files in the cpio archive that fit entirely in the internal buffer, or when no internal
+ * buffer is available, are entirely contained in the buffer fed to cpio_feed(), this callback
+ * is only called once, with reason=CPIO_RNS_FILE_ALL. fileinfo will contain the information
+ * for that specific file (name, size, ...), buff_offset will be 0, buff_len is the file
+ * size and buff contains all the information for the file.
+ *
+ * For files that do not fit in the buffer, this callback will be called multiple times.
+ * The initial time with reason=CPIO_RSN_FILE_INITIAL, when more data is available with
+ * CPIO_RSN_FILE_MORE and finally with CPIO_RSN_FILE_END. For these calls, fileinfo
+ * will again contain file information. buff will be the information contained in the
+ * file at offset buff_offset, and the lenght of this buffer will be in buff_len.
+ *
+ * The library guarantees to feed all file data to the callback consequitively, so
+ * within the same file, the buff_offset from a call will always be (buff_offset+buff_len)
+ * from the call before that. If cpio_start is
+ *
+ * The library also guarantees every file in the cpio archive will either generate a single
+ * callback call with CPIO_RSN_ALL, or multiple with in sequence CPIO_RSN_FILE_INITIAL, 0 or
+ * more CPIO_RSN_FILE_MORE and finally a CPIO_RSN_FILE_END.
+ *
+ * When a non-zero buffer size is passed to cpio_start, the library guarantees that all callback
+ * calls with a reason of CPIO_RSN_FILE_INITIAL and CPIO_RSN_FILE_MORE will have a buffer
+ * filled with exactly this amount of bytes.
+ *
+ */
+typedef void (*cpio_callback_t)(cpio_callback_reason_t reason, cpio_file_t *fileinfo, size_t buff_offset, size_t buff_len, char *buff, void *arg);
+
+
+/**
+ * @brief      Initialize a cpio handle.
+ *
+ * Call this to start parsing a cpio archive. You can set the callback that handles the
+ * files/data here.
+ *
+ * @param  callback The callback that will handle the data of the files inside the cpio archive
+ *
+ * @param  cbarg User-supplied argument. The callback will be called with this as an argument.
+ *
+ * @param  buflen Length of internal buffer used.
+ *                If this is zero, the callback will be called with data that lives in the data buffer
+ *                supplied to the cpio library by whomever called cpio_feed(). Because this library has
+ *                no power over that buffer, the callback can be passed as little as 1 and as many as
+ *                INT_MAX bytes at a time.
+ *                If this is non-zero, the library will allocate an internal buffer of this size. All
+ *                cpio_feed()-calls will be rebuffered, and the callback is guaranteed to only be called
+ *                with this many bytes in the buffer, given there's enough data in the file to fill it.
+ *
+ * @param memchunk Chunk of memory to allocate everything (handle, I/O buffer, filename buffer) in. Minimum size
+ *                 (estimate) is 160+buflen+sizeof(largest filename/path).
+ * @param memchunklen Size of the mem chunk
+ *
+ * @return
+ *     - Success: A pointer to a cpio handle
+ *     - Error: NULL
+ *
+ */
+cpio_handle_t cpio_start(cpio_callback_t callback, void *cbarg, size_t buflen, void *memchunk, int memchunklen);
+
+/**
+ * @brief      Feed data from a cpio archive into the library
+ *
+ * This routine is used to feed consecutive data of the cpio archive into the library. While processing,
+ * the library can call the callback function one or more times if needed.
+ *
+ * @param  cpio Handle obtained by calling cpio_start()
+ *
+ * @param  buffer Pointer to buffer containing cpio archive data
+ *
+ * @param  len Length of the buffer, in bytes
+ *
+ * @return
+ *     - CPIO_RET_MORE: CPIO archive isn't done yet, please feed more data.
+ *     - CPIO_RET_DONE: CPUI archive is finished.
+ *     - CPIO_RET_ERR: Invalid CPIO archive data; decoding aborted.
+ *
+ */
+cpio_ret_t cpio_feed(cpio_handle_t cpio, char *buffer, int len);
+
+/**
+ * @brief      Indicate there is no more cpio data to be fed into the archive
+ *
+ * This call is to be called when the source data is exhausted. Normally, the library can find the end of the
+ * cpio archive by looking for the end marker,
+ *
+ * @param  timer_conf Pointer of LEDC timer configure struct
+ *
+ *
+ * @return
+ *     - CPIO_RET_DONE on success
+ *     - CPIO_RET_ERR when cpio archive is invalid
+ *
+ */
+cpio_ret_t cpio_done(cpio_handle_t cpio);
+
+
+/**
+ * @brief      Free the memory allocated for a cpio handle.
+ *
+ * @param  cpio Handle obtained by calling cpio_start()
+ *
+ * @return
+ *     - CPIO_RET_DONE on success
+ *
+ */
+cpio_ret_t cpio_destroy(cpio_handle_t cpio);
+
+#ifdef __cplusplus
+}
+#endif

+ 174 - 0
components/esp_rom/include/esp32s2/rom/usb/usb_cdc.h

@@ -0,0 +1,174 @@
+/* usb_cdc.h - USB CDC-ACM and CDC-ECM public header */
+
+/*
+ * Copyright (c) 2017 PHYTEC Messtechnik GmbH
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+
+/**
+ * @file
+ * @brief USB Communications Device Class (CDC) public header
+ *
+ * Header follows the Class Definitions for
+ * Communications Devices Specification (CDC120-20101103-track.pdf),
+ * PSTN Devices Specification (PSTN120.pdf) and
+ * Ethernet Control Model Devices Specification (ECM120.pdf).
+ * Header is limited to ACM and ECM Subclasses.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** CDC Specification release number in BCD format */
+#define CDC_SRN_1_20            0x0120
+
+/** Communications Class Subclass Codes */
+#define ACM_SUBCLASS            0x02
+#define ECM_SUBCLASS            0x06
+#define EEM_SUBCLASS            0x0c
+
+/** Communications Class Protocol Codes */
+#define AT_CMD_V250_PROTOCOL        0x01
+#define EEM_PROTOCOL            0x07
+
+/**
+ * @brief Data Class Interface Codes
+ * @note CDC120-20101103-track.pdf, 4.5, Table 6
+ */
+#define DATA_INTERFACE_CLASS        0x0A
+
+/**
+ * @brief Values for the bDescriptorType Field
+ * @note CDC120-20101103-track.pdf, 5.2.3, Table 12
+ */
+#define CS_INTERFACE            0x24
+#define CS_ENDPOINT         0x25
+
+/**
+ * @brief bDescriptor SubType for Communications
+ * Class Functional Descriptors
+ * @note CDC120-20101103-track.pdf, 5.2.3, Table 13
+ */
+#define HEADER_FUNC_DESC        0x00
+#define CALL_MANAGEMENT_FUNC_DESC   0x01
+#define ACM_FUNC_DESC           0x02
+#define UNION_FUNC_DESC         0x06
+#define ETHERNET_FUNC_DESC      0x0F
+
+/**
+ * @brief PSTN Subclass Specific Requests
+ * for ACM devices
+ * @note PSTN120.pdf, 6.3, Table 13
+ */
+#define CDC_SEND_ENC_CMD        0x00
+#define CDC_GET_ENC_RSP         0x01
+#define SET_LINE_CODING         0x20
+#define GET_LINE_CODING         0x21
+#define SET_CONTROL_LINE_STATE      0x22
+
+/** Control Signal Bitmap Values for SetControlLineState */
+#define SET_CONTROL_LINE_STATE_RTS  0x02
+#define SET_CONTROL_LINE_STATE_DTR  0x01
+
+/** UART State Bitmap Values */
+#define SERIAL_STATE_OVERRUN        0x40
+#define SERIAL_STATE_PARITY     0x20
+#define SERIAL_STATE_FRAMING        0x10
+#define SERIAL_STATE_RING       0x08
+#define SERIAL_STATE_BREAK      0x04
+#define SERIAL_STATE_TX_CARRIER     0x02
+#define SERIAL_STATE_RX_CARRIER     0x01
+
+/**
+ * @brief Class-Specific Request Codes for Ethernet subclass
+ * @note ECM120.pdf, 6.2, Table 6
+ */
+#define SET_ETHERNET_MULTICAST_FILTERS  0x40
+#define SET_ETHERNET_PM_FILTER      0x41
+#define GET_ETHERNET_PM_FILTER      0x42
+#define SET_ETHERNET_PACKET_FILTER  0x43
+#define GET_ETHERNET_STATISTIC      0x44
+
+/** Ethernet Packet Filter Bitmap */
+#define PACKET_TYPE_MULTICAST       0x10
+#define PACKET_TYPE_BROADCAST       0x08
+#define PACKET_TYPE_DIRECTED        0x04
+#define PACKET_TYPE_ALL_MULTICAST   0x02
+#define PACKET_TYPE_PROMISCUOUS     0x01
+
+/** Header Functional Descriptor */
+struct cdc_header_descriptor {
+    uint8_t bFunctionLength;
+    uint8_t bDescriptorType;
+    uint8_t bDescriptorSubtype;
+    uint16_t bcdCDC;
+} __packed;
+
+/** Union Interface Functional Descriptor */
+struct cdc_union_descriptor {
+    uint8_t bFunctionLength;
+    uint8_t bDescriptorType;
+    uint8_t bDescriptorSubtype;
+    uint8_t bControlInterface;
+    uint8_t bSubordinateInterface0;
+} __packed;
+
+/** Call Management Functional Descriptor */
+struct cdc_cm_descriptor {
+    uint8_t bFunctionLength;
+    uint8_t bDescriptorType;
+    uint8_t bDescriptorSubtype;
+    uint8_t bmCapabilities;
+    uint8_t bDataInterface;
+} __packed;
+
+/** Abstract Control Management Functional Descriptor */
+struct cdc_acm_descriptor {
+    uint8_t bFunctionLength;
+    uint8_t bDescriptorType;
+    uint8_t bDescriptorSubtype;
+    uint8_t bmCapabilities;
+} __packed;
+
+
+/** Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */
+struct cdc_acm_line_coding {
+    uint32_t dwDTERate;
+    uint8_t bCharFormat;
+    uint8_t bParityType;
+    uint8_t bDataBits;
+} __packed;
+
+/** Data structure for the notification about SerialState */
+struct cdc_acm_notification {
+    uint8_t bmRequestType;
+    uint8_t bNotificationType;
+    uint16_t wValue;
+    uint16_t wIndex;
+    uint16_t wLength;
+    uint16_t data;
+} __packed;
+
+/** Ethernet Networking Functional Descriptor */
+struct cdc_ecm_descriptor {
+    uint8_t bFunctionLength;
+    uint8_t bDescriptorType;
+    uint8_t bDescriptorSubtype;
+    uint8_t iMACAddress;
+    uint32_t bmEthernetStatistics;
+    uint16_t wMaxSegmentSize;
+    uint16_t wNumberMCFilters;
+    uint8_t bNumberPowerFilters;
+} __packed;
+
+#ifdef __cplusplus
+}
+#endif

+ 244 - 0
components/esp_rom/include/esp32s2/rom/usb/usb_common.h

@@ -0,0 +1,244 @@
+/***************************************************************************
+ *
+ *
+ * Copyright(c) 2015,2016 Intel Corporation.
+ * Copyright(c) 2017 PHYTEC Messtechnik GmbH
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ***************************************************************************/
+
+/**
+ * @file
+ * @brief useful constants and macros for the USB application
+ *
+ * This file contains useful constants and macros for the USB applications.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BCD(x) ((((x) / 10) << 4) | ((x) / 10))
+
+/* Descriptor size in bytes */
+#define USB_DEVICE_DESC_SIZE        18
+#define USB_CONFIGURATION_DESC_SIZE 9
+#define USB_INTERFACE_DESC_SIZE     9
+#define USB_ENDPOINT_DESC_SIZE      7
+#define USB_STRING_DESC_SIZE        4
+#define USB_HID_DESC_SIZE       9
+#define USB_DFU_DESC_SIZE       9
+#define USB_DEVICE_QUAL_DESC_SIZE   10
+#define USB_INTERFACE_ASSOC_DESC_SIZE   8
+
+/* Descriptor type */
+#define USB_DEVICE_DESC         0x01
+#define USB_CONFIGURATION_DESC      0x02
+#define USB_STRING_DESC         0x03
+#define USB_INTERFACE_DESC      0x04
+#define USB_ENDPOINT_DESC       0x05
+#define USB_DEVICE_QUAL_DESC        0x06
+#define USB_INTERFACE_ASSOC_DESC    0x0B
+#define USB_DEVICE_CAPABILITY_DESC  0x10
+#define USB_HID_DESC            0x21
+#define USB_HID_REPORT_DESC     0x22
+#define USB_DFU_FUNCTIONAL_DESC     0x21
+#define USB_ASSOCIATION_DESC        0x0B
+#define USB_BINARY_OBJECT_STORE_DESC    0x0F
+
+/* Useful define */
+#define USB_1_1             0x0110
+#define USB_2_0             0x0200
+/* Set USB version to 2.1 so that the host will request the BOS descriptor */
+#define USB_2_1             0x0210
+
+#define BCDDEVICE_RELNUM        (BCD(KERNEL_VERSION_MAJOR) << 8 | \
+                    BCD(KERNEL_VERSION_MINOR))
+
+/* 100mA max power, per 2mA units */
+/* USB 1.1 spec indicates 100mA(max) per unit load, up to 5 loads */
+#define MAX_LOW_POWER           0x32
+#define MAX_HIGH_POWER          0xFA
+
+/* bmAttributes:
+ * D7:Reserved, always 1,
+ * D6:Self-Powered -> 1,
+ * D5:Remote Wakeup -> 0,
+ * D4...0:Reserved -> 0
+ */
+#define USB_CONFIGURATION_ATTRIBUTES    0xC0
+
+/* Classes */
+#define COMMUNICATION_DEVICE_CLASS  0x02
+#define COMMUNICATION_DEVICE_CLASS_DATA 0x0A
+#define HID_CLASS           0x03
+#define MASS_STORAGE_CLASS      0x08
+#define WIRELESS_DEVICE_CLASS       0xE0
+#define MISC_CLASS          0xEF
+#define CUSTOM_CLASS            0xFF
+#define DFU_DEVICE_CLASS        0xFE
+
+/* Sub-classes */
+#define CDC_NCM_SUBCLASS        0x0d
+#define BOOT_INTERFACE_SUBCLASS     0x01
+#define SCSI_TRANSPARENT_SUBCLASS   0x06
+#define DFU_INTERFACE_SUBCLASS      0x01
+#define RF_SUBCLASS         0x01
+#define CUSTOM_SUBCLASS         0xFF
+#define COMMON_SUBCLASS         0x02
+/* Misc subclasses */
+#define MISC_RNDIS_SUBCLASS     0x04
+#define CDC_ABSTRACT_CONTROL_MODEL 0x02
+
+/* Protocols */
+#define V25TER_PROTOCOL         0x01
+#define MOUSE_PROTOCOL          0x02
+#define BULK_ONLY_PROTOCOL      0x50
+#define DFU_RUNTIME_PROTOCOL        0x01
+#define DFU_MODE_PROTOCOL       0x02
+#define BLUETOOTH_PROTOCOL      0x01
+/* CDC ACM protocols */
+#define ACM_VENDOR_PROTOCOL     0xFF
+/* Misc protocols */
+#define MISC_ETHERNET_PROTOCOL      0x01
+#define IAD_PROTOCOL            0x01
+
+/** Standard Device Descriptor */
+struct usb_device_descriptor {
+    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;
+} __packed;
+
+/** Unicode (UTF16LE) String Descriptor */
+struct usb_string_descriptor {
+    uint8_t bLength;
+    uint8_t bDescriptorType;
+    uint16_t bString;
+} __packed;
+
+/** Association Descriptor */
+struct usb_association_descriptor {
+    uint8_t bLength;
+    uint8_t bDescriptorType;
+    uint8_t bFirstInterface;
+    uint8_t bInterfaceCount;
+    uint8_t bFunctionClass;
+    uint8_t bFunctionSubClass;
+    uint8_t bFunctionProtocol;
+    uint8_t iFunction;
+} __packed;
+
+/** Standard Configuration Descriptor */
+struct usb_cfg_descriptor {
+    uint8_t bLength;
+    uint8_t bDescriptorType;
+    uint16_t wTotalLength;
+    uint8_t bNumInterfaces;
+    uint8_t bConfigurationValue;
+    uint8_t iConfiguration;
+    uint8_t bmAttributes;
+    uint8_t bMaxPower;
+} __packed;
+
+/** Standard Interface Descriptor */
+struct usb_if_descriptor {
+    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;
+} __packed;
+
+/** Standard Endpoint Descriptor */
+struct usb_ep_descriptor {
+    uint8_t bLength;
+    uint8_t bDescriptorType;
+    uint8_t bEndpointAddress;
+    uint8_t bmAttributes;
+    uint16_t wMaxPacketSize;
+    uint8_t bInterval;
+} __packed;
+
+struct string_descriptor_zero {
+    uint8_t bLength;
+    uint8_t bDescriptorType;
+    uint16_t wBcdLang[];
+} __packed;
+
+struct string_descriptor {
+    uint8_t bLength;
+    uint8_t bDescriptorType;
+    uint16_t bString[];
+} __packed;
+
+#define ROM_MAX_CFG_DESC_CNT 1
+
+struct rom_usb_descriptors {
+    const struct usb_device_descriptor *device_descr;
+    const void *config_descr[ROM_MAX_CFG_DESC_CNT];
+    int string_count; // including string_descriptor_zero
+    const struct string_descriptor_zero *string0_descr;
+    const struct string_descriptor *string_descrs[];
+};
+
+/* Descriptors defined in the ROM */
+extern struct usb_device_descriptor general_device_descr;
+extern const void* acm_config_descr;
+extern const void* dfu_config_descr;
+extern const struct string_descriptor str_manu_descr;
+extern const struct string_descriptor str_prod_descr;
+extern const struct string_descriptor_zero string0_descr;
+extern const struct rom_usb_descriptors acm_usb_descriptors;
+extern const struct rom_usb_descriptors dfu_usb_descriptors;
+extern const struct rom_usb_descriptors *rom_usb_curr_desc;
+
+
+#ifdef __cplusplus
+}
+#endif

+ 392 - 0
components/esp_rom/include/esp32s2/rom/usb/usb_dc.h

@@ -0,0 +1,392 @@
+/* usb_dc.h - USB device controller driver interface */
+
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief USB device controller APIs
+ *
+ * This file contains the USB device controller APIs. All device controller
+ * drivers should implement the APIs described in this file.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * USB endpoint direction and number.
+ */
+
+#define USB_EP_DIR_MASK 0x80
+#define USB_EP_DIR_IN   0x80
+#define USB_EP_DIR_OUT  0x00
+
+/**
+ * USB Driver Status Codes
+ */
+enum usb_dc_status_code {
+    USB_DC_ERROR,        /* USB error reported by the controller */
+    USB_DC_RESET,        /* USB reset */
+    /* USB connection established, hardware enumeration is completed */
+    USB_DC_CONNECTED,
+    USB_DC_CONFIGURED,   /* USB configuration done */
+    USB_DC_DISCONNECTED, /* USB connection lost */
+    USB_DC_SUSPEND,      /* USB connection suspended by the HOST */
+    USB_DC_RESUME,       /* USB connection resumed by the HOST */
+    USB_DC_INTERFACE,    /* USB interface selected */
+    USB_DC_SET_HALT,     /* Set Feature ENDPOINT_HALT received */
+    USB_DC_CLEAR_HALT,   /* Clear Feature ENDPOINT_HALT received */
+    USB_DC_UNKNOWN       /* Initial USB connection status */
+};
+
+/**
+ * USB Endpoint Callback Status Codes
+ */
+enum usb_dc_ep_cb_status_code {
+    USB_DC_EP_SETUP,    /* SETUP received */
+    /* Out transaction on this EP, data is available for read */
+    USB_DC_EP_DATA_OUT,
+    USB_DC_EP_DATA_IN,  /* In transaction done on this EP */
+};
+
+/**
+ * USB Endpoint type
+ */
+enum usb_dc_ep_type {
+    USB_DC_EP_CONTROL = 0,  /* Control type endpoint */
+    USB_DC_EP_ISOCHRONOUS,  /* Isochronous type endpoint */
+    USB_DC_EP_BULK,         /* Bulk type endpoint */
+    USB_DC_EP_INTERRUPT     /* Interrupt type endpoint  */
+};
+
+/**
+ * USB Endpoint Configuration.
+ */
+struct usb_dc_ep_cfg_data {
+    /** The number associated with the EP in the device
+     *  configuration structure
+     *       IN  EP = 0x80 | \<endpoint number\>
+     *       OUT EP = 0x00 | \<endpoint number\>
+     */
+    uint8_t ep_addr;
+    uint16_t ep_mps;             /** Endpoint max packet size */
+    enum usb_dc_ep_type ep_type; /** Endpoint type */
+};
+
+/**
+ * Callback function signature for the USB Endpoint status
+ */
+typedef void (*usb_dc_ep_callback)(uint8_t ep,
+                                   enum usb_dc_ep_cb_status_code cb_status);
+
+/**
+ * Callback function signature for the device
+ */
+typedef void (*usb_dc_status_callback)(enum usb_dc_status_code cb_status,
+                                       uint8_t *param);
+
+/**
+ * @brief attach USB for device connection
+ *
+ * Function to attach USB for device connection. Upon success, the USB PLL
+ * is enabled, and the USB device is now capable of transmitting and receiving
+ * on the USB bus and of generating interrupts.
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_dc_attach(void);
+
+/**
+ * @brief detach the USB device
+ *
+ * Function to detach the USB device. Upon success, the USB hardware PLL
+ * is powered down and USB communication is disabled.
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_dc_detach(void);
+
+/**
+ * @brief reset the USB device
+ *
+ * This function returns the USB device and firmware back to it's initial state.
+ * N.B. the USB PLL is handled by the usb_detach function
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_dc_reset(void);
+
+/**
+ * @brief set USB device address
+ *
+ * @param[in] addr device address
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_dc_set_address(const uint8_t addr);
+
+/**
+ * @brief set USB device controller status callback
+ *
+ * Function to set USB device controller status callback. The registered
+ * callback is used to report changes in the status of the device controller.
+ *
+ * @param[in] cb callback function
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_dc_set_status_callback(const usb_dc_status_callback cb);
+
+/**
+ * @brief check endpoint capabilities
+ *
+ * Function to check capabilities of an endpoint. usb_dc_ep_cfg_data structure
+ * provides the endpoint configuration parameters: endpoint address,
+ * endpoint maximum packet size and endpoint type.
+ * The driver should check endpoint capabilities and return 0 if the
+ * endpoint configuration is possible.
+ *
+ * @param[in] cfg Endpoint config
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_dc_ep_check_cap(const struct usb_dc_ep_cfg_data *const cfg);
+
+/**
+ * @brief configure endpoint
+ *
+ * Function to configure an endpoint. usb_dc_ep_cfg_data structure provides
+ * the endpoint configuration parameters: endpoint address, endpoint maximum
+ * packet size and endpoint type.
+ *
+ * @param[in] cfg Endpoint config
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_dc_ep_configure(const struct usb_dc_ep_cfg_data *const cfg);
+
+/**
+ * @brief set stall condition for the selected endpoint
+ *
+ * @param[in] ep Endpoint address corresponding to the one
+ *               listed in the device configuration table
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_dc_ep_set_stall(const uint8_t ep);
+
+/**
+ * @brief clear stall condition for the selected endpoint
+ *
+ * @param[in] ep Endpoint address corresponding to the one
+ *               listed in the device configuration table
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_dc_ep_clear_stall(const uint8_t ep);
+
+/**
+ * @brief check if selected endpoint is stalled
+ *
+ * @param[in]  ep       Endpoint address corresponding to the one
+ *                      listed in the device configuration table
+ * @param[out] stalled  Endpoint stall status
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_dc_ep_is_stalled(const uint8_t ep, uint8_t *const stalled);
+
+/**
+ * @brief halt the selected endpoint
+ *
+ * @param[in] ep Endpoint address corresponding to the one
+ *               listed in the device configuration table
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_dc_ep_halt(const uint8_t ep);
+
+/**
+ * @brief enable the selected endpoint
+ *
+ * Function to enable the selected endpoint. Upon success interrupts are
+ * enabled for the corresponding endpoint and the endpoint is ready for
+ * transmitting/receiving data.
+ *
+ * @param[in] ep Endpoint address corresponding to the one
+ *               listed in the device configuration table
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_dc_ep_enable(const uint8_t ep);
+
+/**
+ * @brief disable the selected endpoint
+ *
+ * Function to disable the selected endpoint. Upon success interrupts are
+ * disabled for the corresponding endpoint and the endpoint is no longer able
+ * for transmitting/receiving data.
+ *
+ * @param[in] ep Endpoint address corresponding to the one
+ *               listed in the device configuration table
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_dc_ep_disable(const uint8_t ep);
+
+/**
+ * @brief flush the selected endpoint
+ *
+ * @param[in] ep Endpoint address corresponding to the one
+ *               listed in the device configuration table
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_dc_ep_flush(const uint8_t ep);
+
+/**
+ * @brief write data to the specified endpoint
+ *
+ * This function is called to write data to the specified endpoint. The supplied
+ * usb_ep_callback function will be called when data is transmitted out.
+ *
+ * @param[in]  ep        Endpoint address corresponding to the one
+ *                       listed in the device configuration table
+ * @param[in]  data      pointer to data to write
+ * @param[in]  data_len  length of data requested to write. This may
+ *                       be zero for a zero length status packet.
+ * @param[out] ret_bytes bytes scheduled for transmission. This value
+ *                       may be NULL if the application expects all
+ *                       bytes to be written
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_dc_ep_write(const uint8_t ep, const uint8_t *const data,
+                    const uint32_t data_len, uint32_t *const ret_bytes);
+
+
+
+/**
+ * @brief Indicate if the write to an IN endpoint (using usb_dc_ep_write) would block
+ * to wait until the endpoint has enoug space
+ *
+ * @param[in]  ep        Endpoint address corresponding to the one
+ *                       listed in the device configuration table
+ *
+ * @return 0 when writable, 0 when not, negative errno code on fail.
+ */
+int usb_dc_ep_write_would_block(const uint8_t ep);
+
+
+/**
+ * @brief read data from the specified endpoint
+ *
+ * This function is called by the Endpoint handler function, after an OUT
+ * interrupt has been received for that EP. The application must only call this
+ * function through the supplied usb_ep_callback function. This function clears
+ * the ENDPOINT NAK, if all data in the endpoint FIFO has been read,
+ * so as to accept more data from host.
+ *
+ * @param[in]  ep           Endpoint address corresponding to the one
+ *                          listed in the device configuration table
+ * @param[in]  data         pointer to data buffer to write to
+ * @param[in]  max_data_len max length of data to read
+ * @param[out] read_bytes   Number of bytes read. If data is NULL and
+ *                          max_data_len is 0 the number of bytes
+ *                          available for read should be returned.
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_dc_ep_read(const uint8_t ep, uint8_t *const data,
+                   const uint32_t max_data_len, uint32_t *const read_bytes);
+
+/**
+ * @brief set callback function for the specified endpoint
+ *
+ * Function to set callback function for notification of data received and
+ * available to application or transmit done on the selected endpoint,
+ * NULL if callback not required by application code.
+ *
+ * @param[in] ep Endpoint address corresponding to the one
+ *               listed in the device configuration table
+ * @param[in] cb callback function
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_dc_ep_set_callback(const uint8_t ep, const usb_dc_ep_callback cb);
+
+/**
+ * @brief read data from the specified endpoint
+ *
+ * This is similar to usb_dc_ep_read, the difference being that, it doesn't
+ * clear the endpoint NAKs so that the consumer is not bogged down by further
+ * upcalls till he is done with the processing of the data. The caller should
+ * reactivate ep by invoking usb_dc_ep_read_continue() do so.
+ *
+ * @param[in]  ep           Endpoint address corresponding to the one
+ *                          listed in the device configuration table
+ * @param[in]  data         pointer to data buffer to write to
+ * @param[in]  max_data_len max length of data to read
+ * @param[out] read_bytes   Number of bytes read. If data is NULL and
+ *                          max_data_len is 0 the number of bytes
+ *                          available for read should be returned.
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_dc_ep_read_wait(uint8_t ep, uint8_t *data, uint32_t max_data_len,
+                        uint32_t *read_bytes);
+
+
+/**
+ * @brief Continue reading data from the endpoint
+ *
+ * Clear the endpoint NAK and enable the endpoint to accept more data
+ * from the host. Usually called after usb_dc_ep_read_wait() when the consumer
+ * is fine to accept more data. Thus these calls together acts as flow control
+ * mechanism.
+ *
+ * @param[in]  ep           Endpoint address corresponding to the one
+ *                          listed in the device configuration table
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_dc_ep_read_continue(uint8_t ep);
+
+/**
+ * @brief Get endpoint max packet size
+ *
+ * @param[in]  ep           Endpoint address corresponding to the one
+ *                          listed in the device configuration table
+ *
+ * @return enpoint max packet size (mps)
+ */
+int usb_dc_ep_mps(uint8_t ep);
+
+
+
+//Hack - fake interrupts by pollinfg
+void usb_dc_check_poll_for_interrupts(void);
+
+
+//Prepare for USB persist. You should reboot after this.
+int usb_dc_prepare_persist(void);
+
+
+void usb_dw_isr_handler(void);
+
+
+int usb_dc_ep_write_would_block(const uint8_t ep);
+
+
+#ifdef __cplusplus
+}
+#endif

+ 34 - 0
components/esp_rom/include/esp32s2/rom/usb/usb_descriptor.h

@@ -0,0 +1,34 @@
+// Copyright 2019-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
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define USB_DESCRIPTOR_TYPE_ACM 0
+#define USB_DESCRIPTOR_TYPE_DFU 1
+
+void usb_set_current_descriptor(int descriptor_type);
+
+bool usb_get_descriptor(uint16_t type_index, uint16_t lang_id,
+                        int32_t *len, uint8_t **data);
+
+#ifdef __cplusplus
+}
+#endif

+ 402 - 0
components/esp_rom/include/esp32s2/rom/usb/usb_device.h

@@ -0,0 +1,402 @@
+/*
+ *  LPCUSB, an USB device driver for LPC microcontrollers
+ *  Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+ *  Copyright (c) 2016 Intel Corporation
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief USB device core layer APIs and structures
+ *
+ * This file contains the USB device core layer APIs and structures.
+ */
+
+#pragma once
+
+#include <stddef.h>
+#include <sys/cdefs.h>
+#include "usb_dc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*************************************************************************
+ *  USB configuration
+ **************************************************************************/
+
+#define MAX_PACKET_SIZE0    64        /**< maximum packet size for EP 0 */
+//Note: for FS this should be 8, 16, 32, 64 bytes. HS can go up to 512.
+
+/*************************************************************************
+ *  USB application interface
+ **************************************************************************/
+
+/** setup packet definitions */
+struct usb_setup_packet {
+    uint8_t bmRequestType;  /**< characteristics of the specific request */
+    uint8_t bRequest;       /**< specific request */
+    uint16_t wValue;        /**< request specific parameter */
+    uint16_t wIndex;        /**< request specific parameter */
+    uint16_t wLength;       /**< length of data transferred in data phase */
+} __packed;
+
+
+_Static_assert(sizeof(struct usb_setup_packet) == 8, "USB setup packet struct size error");
+
+/**
+ * Callback function signature for the device
+ */
+typedef void (*usb_status_callback)(enum usb_dc_status_code status_code,
+                                    uint8_t *param);
+
+/**
+ * Callback function signature for the USB Endpoint status
+ */
+typedef void (*usb_ep_callback)(uint8_t ep,
+                                enum usb_dc_ep_cb_status_code cb_status);
+
+/**
+ * Function which handles Class specific requests corresponding to an
+ * interface number specified in the device descriptor table
+ */
+typedef int (*usb_request_handler) (struct usb_setup_packet *detup,
+                                    int32_t *transfer_len, uint8_t **payload_data);
+
+/**
+ * Function for interface runtime configuration
+ */
+typedef void (*usb_interface_config)(uint8_t bInterfaceNumber);
+
+/*
+ * USB Endpoint Configuration
+ */
+struct usb_ep_cfg_data {
+    /**
+     * Callback function for notification of data received and
+     * available to application or transmit done, NULL if callback
+     * not required by application code
+     */
+    usb_ep_callback ep_cb;
+    /**
+     * The number associated with the EP in the device configuration
+     * structure
+     *   IN  EP = 0x80 | \<endpoint number\>
+     *   OUT EP = 0x00 | \<endpoint number\>
+     */
+    uint8_t ep_addr;
+};
+
+/**
+ * USB Interface Configuration
+ */
+struct usb_interface_cfg_data {
+    /** Handler for USB Class specific Control (EP 0) communications */
+    usb_request_handler class_handler;
+    /** Handler for USB Vendor specific commands */
+    usb_request_handler vendor_handler;
+    /**
+     * The custom request handler gets a first chance at handling
+     * the request before it is handed over to the 'chapter 9' request
+     * handler
+     */
+    usb_request_handler custom_handler;
+    /**
+     * This data area, allocated by the application, is used to store
+     * Class specific command data and must be large enough to store the
+     * largest payload associated with the largest supported Class'
+     * command set. This data area may be used for USB IN or OUT
+     * communications
+     */
+    uint8_t *payload_data;
+    /**
+     * This data area, allocated by the application, is used to store
+     * Vendor specific payload
+     */
+    uint8_t *vendor_data;
+};
+
+/*
+ * @brief USB device configuration
+ *
+ * The Application instantiates this with given parameters added
+ * using the "usb_set_config" function. Once this function is called
+ * changes to this structure will result in undefined behaviour. This structure
+ * may only be updated after calls to usb_deconfig
+ */
+struct usb_cfg_data {
+    /**
+     * USB device description, see
+     * http://www.beyondlogic.org/usbnutshell/usb5.shtml#DeviceDescriptors
+     */
+    const uint8_t *usb_device_description;
+    /** Pointer to interface descriptor */
+    const void *interface_descriptor;
+    /** Function for interface runtime configuration */
+    usb_interface_config interface_config;
+    /** Callback to be notified on USB connection status change */
+    usb_status_callback cb_usb_status;
+    /** USB interface (Class) handler and storage space */
+    struct usb_interface_cfg_data interface;
+    /** Number of individual endpoints in the device configuration */
+    uint8_t num_endpoints;
+    /**
+     * Pointer to an array of endpoint structs of length equal to the
+     * number of EP associated with the device description,
+     * not including control endpoints
+     */
+    struct usb_ep_cfg_data *endpoint;
+};
+
+/*
+ * @brief configure USB controller
+ *
+ * Function to configure USB controller.
+ * Configuration parameters must be valid or an error is returned
+ *
+ * @param[in] config Pointer to configuration structure
+ *
+ * @return 0 on success, negative errno code on fail
+ */
+int usb_set_config(struct usb_cfg_data *config);
+
+/*
+ * @brief return the USB device to it's initial state
+ *
+ * @return 0 on success, negative errno code on fail
+ */
+int usb_deconfig(void);
+
+/*
+ * @brief enable USB for host/device connection
+ *
+ * Function to enable USB for host/device connection.
+ * Upon success, the USB module is no longer clock gated in hardware,
+ * it is now capable of transmitting and receiving on the USB bus and
+ * of generating interrupts.
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_enable(struct usb_cfg_data *config);
+
+/*
+ * @brief disable the USB device.
+ *
+ * Function to disable the USB device.
+ * Upon success, the specified USB interface is clock gated in hardware,
+ * it is no longer capable of generating interrupts.
+ *
+ * @return 0 on success, negative errno code on fail
+ */
+int usb_disable(void);
+
+/*
+ * @brief Check if a write to an in ep would block until there is enough space
+ * in the fifo
+ *
+ * @param[in]  ep        Endpoint address corresponding to the one listed in the
+ *                       device configuration table
+ *
+ * @return 0 if free to write, 1 if a write would block, negative errno code on fail
+ */
+int usb_write_would_block(uint8_t ep);
+
+/*
+ * @brief write data to the specified endpoint
+ *
+ * Function to write data to the specified endpoint. The supplied
+ * usb_ep_callback will be called when transmission is done.
+ *
+ * @param[in]  ep        Endpoint address corresponding to the one listed in the
+ *                       device configuration table
+ * @param[in]  data      Pointer to data to write
+ * @param[in]  data_len  Length of data requested to write. This may be zero for
+ *                       a zero length status packet.
+ * @param[out] bytes_ret Bytes written to the EP FIFO. This value may be NULL if
+ *                       the application expects all bytes to be written
+ *
+ * @return 0 on success, negative errno code on fail
+ */
+int usb_write(uint8_t ep, const uint8_t *data, uint32_t data_len,
+              uint32_t *bytes_ret);
+
+/*
+ * @brief read data from the specified endpoint
+ *
+ * This function is called by the Endpoint handler function, after an
+ * OUT interrupt has been received for that EP. The application must
+ * only call this function through the supplied usb_ep_callback function.
+ *
+ * @param[in]  ep           Endpoint address corresponding to the one listed in
+ *                          the device configuration table
+ * @param[in]  data         Pointer to data buffer to write to
+ * @param[in]  max_data_len Max length of data to read
+ * @param[out] ret_bytes    Number of bytes read. If data is NULL and
+ *                          max_data_len is 0 the number of bytes available
+ *                          for read is returned.
+ *
+ * @return  0 on success, negative errno code on fail
+ */
+int usb_read(uint8_t ep, uint8_t *data, uint32_t max_data_len,
+             uint32_t *ret_bytes);
+
+/*
+ * @brief set STALL condition on the specified endpoint
+ *
+ * This function is called by USB device class handler code to set stall
+ * conditionin on endpoint.
+ *
+ * @param[in]  ep           Endpoint address corresponding to the one listed in
+ *                          the device configuration table
+ *
+ * @return  0 on success, negative errno code on fail
+ */
+int usb_ep_set_stall(uint8_t ep);
+
+
+/*
+ * @brief clears STALL condition on the specified endpoint
+ *
+ * This function is called by USB device class handler code to clear stall
+ * conditionin on endpoint.
+ *
+ * @param[in]  ep           Endpoint address corresponding to the one listed in
+ *                          the device configuration table
+ *
+ * @return  0 on success, negative errno code on fail
+ */
+int usb_ep_clear_stall(uint8_t ep);
+
+/**
+ * @brief read data from the specified endpoint
+ *
+ * This is similar to usb_ep_read, the difference being that, it doesn't
+ * clear the endpoint NAKs so that the consumer is not bogged down by further
+ * upcalls till he is done with the processing of the data. The caller should
+ * reactivate ep by invoking usb_ep_read_continue() do so.
+ *
+ * @param[in]  ep           Endpoint address corresponding to the one
+ *                          listed in the device configuration table
+ * @param[in]  data         pointer to data buffer to write to
+ * @param[in]  max_data_len max length of data to read
+ * @param[out] read_bytes   Number of bytes read. If data is NULL and
+ *                          max_data_len is 0 the number of bytes
+ *                          available for read should be returned.
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_ep_read_wait(uint8_t ep, uint8_t *data, uint32_t max_data_len,
+                     uint32_t *read_bytes);
+
+
+/**
+ * @brief Continue reading data from the endpoint
+ *
+ * Clear the endpoint NAK and enable the endpoint to accept more data
+ * from the host. Usually called after usb_ep_read_wait() when the consumer
+ * is fine to accept more data. Thus these calls together acts as flow control
+ * mechanism.
+ *
+ * @param[in]  ep           Endpoint address corresponding to the one
+ *                          listed in the device configuration table
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_ep_read_continue(uint8_t ep);
+
+/**
+ * Callback function signature for transfer completion.
+ */
+typedef void (*usb_transfer_callback)(uint8_t ep, int tsize, void *priv);
+
+/* USB transfer flags */
+#define USB_TRANS_READ       BIT(0)   /** Read transfer flag */
+#define USB_TRANS_WRITE      BIT(1)   /** Write transfer flag */
+#define USB_TRANS_NO_ZLP     BIT(2)   /** No zero-length packet flag */
+
+/**
+ * @brief Transfer management endpoint callback
+ *
+ * If a USB class driver wants to use high-level transfer functions, driver
+ * needs to register this callback as usb endpoint callback.
+ */
+void usb_transfer_ep_callback(uint8_t ep, enum usb_dc_ep_cb_status_code);
+
+/**
+ * @brief Start a transfer
+ *
+ * Start a usb transfer to/from the data buffer. This function is asynchronous
+ * and can be executed in IRQ context. The provided callback will be called
+ * on transfer completion (or error) in thread context.
+ *
+ * @param[in]  ep           Endpoint address corresponding to the one
+ *                          listed in the device configuration table
+ * @param[in]  data         Pointer to data buffer to write-to/read-from
+ * @param[in]  dlen         Size of data buffer
+ * @param[in]  flags        Transfer flags (USB_TRANS_READ, USB_TRANS_WRITE...)
+ * @param[in]  cb           Function called on transfer completion/failure
+ * @param[in]  priv         Data passed back to the transfer completion callback
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usb_transfer(uint8_t ep, uint8_t *data, size_t dlen, unsigned int flags,
+                 usb_transfer_callback cb, void *priv);
+
+/**
+ * @brief Start a transfer and block-wait for completion
+ *
+ * Synchronous version of usb_transfer, wait for transfer completion before
+ * returning.
+ *
+ * @param[in]  ep           Endpoint address corresponding to the one
+ *                          listed in the device configuration table
+ * @param[in]  data         Pointer to data buffer to write-to/read-from
+ * @param[in]  dlen         Size of data buffer
+ * @param[in]  flags        Transfer flags
+
+ *
+ * @return number of bytes transferred on success, negative errno code on fail.
+ */
+int usb_transfer_sync(uint8_t ep, uint8_t *data, size_t dlen, unsigned int flags);
+
+/**
+ * @brief Cancel any ongoing transfer on the specified endpoint
+ *
+ * @param[in]  ep           Endpoint address corresponding to the one
+ *                          listed in the device configuration table
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+void usb_cancel_transfer(uint8_t ep);
+
+
+void usb_dev_resume(int configuration);
+int usb_dev_get_configuration(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+

+ 147 - 0
components/esp_rom/include/esp32s2/rom/usb/usb_dfu.h

@@ -0,0 +1,147 @@
+/***************************************************************************
+ *
+ * Copyright(c) 2015,2016 Intel Corporation.
+ * Copyright(c) 2017 PHYTEC Messtechnik GmbH
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ***************************************************************************/
+
+/**
+ * @file
+ * @brief USB Device Firmware Upgrade (DFU) public header
+ *
+ * Header follows the Device Class Specification for
+ * Device Firmware Upgrade Version 1.1
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <stddef.h>
+#include "usb_device.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** DFU Class Subclass */
+#define DFU_SUBCLASS            0x01
+
+/** DFU Class runtime Protocol */
+#define DFU_RT_PROTOCOL         0x01
+
+/** DFU Class DFU mode Protocol */
+#define DFU_MODE_PROTOCOL       0x02
+
+/**
+ * @brief DFU Class Specific Requests
+ */
+#define DFU_DETACH          0x00
+#define DFU_DNLOAD          0x01
+#define DFU_UPLOAD          0x02
+#define DFU_GETSTATUS           0x03
+#define DFU_CLRSTATUS           0x04
+#define DFU_GETSTATE            0x05
+#define DFU_ABORT           0x06
+
+/** DFU FUNCTIONAL descriptor type */
+#define DFU_FUNC_DESC           0x21
+
+/** DFU attributes DFU Functional Descriptor */
+#define DFU_ATTR_WILL_DETACH        0x08
+#define DFU_ATTR_MANIFESTATION_TOLERANT 0x04
+#define DFU_ATTR_CAN_UPLOAD     0x02
+#define DFU_ATTR_CAN_DNLOAD     0x01
+
+/** DFU Specification release */
+#define DFU_VERSION         0x0110
+
+/** Run-Time Functional Descriptor */
+struct dfu_runtime_descriptor {
+    uint8_t bLength;
+    uint8_t bDescriptorType;
+    uint8_t bmAttributes;
+    uint16_t wDetachTimeOut;
+    uint16_t wTransferSize;
+    uint16_t bcdDFUVersion;
+} __packed;
+
+/** bStatus values for the DFU_GETSTATUS response */
+enum dfu_status {
+    statusOK,
+    errTARGET,
+    errFILE,
+    errWRITE,
+    errERASE,
+    errCHECK_ERASED,
+    errPROG,
+    errVERIFY,
+    errADDRESS,
+    errNOTDONE,
+    errFIRMWARE,
+    errVENDOR,
+    errUSB,
+    errPOR,
+    errUNKNOWN,
+    errSTALLEDPKT
+};
+
+/** bState values for the DFU_GETSTATUS response */
+enum dfu_state {
+    appIDLE,
+    appDETACH,
+    dfuIDLE,
+    dfuDNLOAD_SYNC,
+    dfuDNBUSY,
+    dfuDNLOAD_IDLE,
+    dfuMANIFEST_SYNC,
+    dfuMANIFEST,
+    dfuMANIFEST_WAIT_RST,
+    dfuUPLOAD_IDLE,
+    dfuERROR,
+};
+
+/*
+ These callbacks are made public so the ACM driver can call them to handle the switch to DFU.
+*/
+
+int dfu_class_handle_req(struct usb_setup_packet *pSetup,
+                         int32_t *data_len, uint8_t **data);
+void dfu_status_cb(enum usb_dc_status_code status, uint8_t *param);
+int usb_dfu_init(void);
+int dfu_custom_handle_req(struct usb_setup_packet *pSetup,
+                          int32_t *data_len, uint8_t **data);
+
+
+typedef void(*usb_dfu_detach_routine_t)(int delay);
+void usb_dfu_set_detach_cb(usb_dfu_detach_routine_t cb);
+
+
+#ifdef __cplusplus
+}
+#endif

+ 40 - 0
components/esp_rom/include/esp32s2/rom/usb/usb_os_glue.h

@@ -0,0 +1,40 @@
+// Copyright 2019-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
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef void(*usb_osglue_intdisena_routine_t)(void);
+typedef int(*usb_osglue_wait_routine_t)(int delay_us);
+
+typedef struct {
+    /* Disable USB interrupt */
+    usb_osglue_intdisena_routine_t int_dis_proc;
+    /* Enable USB interrupt */
+    usb_osglue_intdisena_routine_t int_ena_proc;
+    /* Wait for a set amount of uS. Return the amount actually waited. If delay_us is 0, just yield.*/
+    usb_osglue_wait_routine_t wait_proc;
+} usb_osglue_data_t;
+
+extern usb_osglue_data_t rom_usb_osglue;
+
+#ifdef __cplusplus
+}
+#endif

+ 50 - 0
components/esp_rom/include/esp32s2/rom/usb/usb_persist.h

@@ -0,0 +1,50 @@
+// Copyright 2019-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
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// USB persistence flags.
+
+//This bit indicates persistence has been enabled, that is, the USB initialization routines should not
+//reset the USB device as the device still is initialized and the host detected it with the same cdcacm/dfu
+//descriptor as the ROM uses; we can just re-initialize the software side and have at 'er.
+#define USBDC_PERSIST_ENA (1<<31)
+
+//This bit indicates to the ROM that we rebooted because of a request to go into DFU mode; the ROM should
+//honour this request.
+#define USBDC_BOOT_DFU (1<<30)
+
+
+//This being non-0 indicates a memory location where a 'testament' is stored, aka a piece of text that should be output
+//after a reboot. Can contain core dump info or something.
+#define USBDC_TESTAMENT_LOC_MASK 0x7FFFF //bits 19-0; this is added to a base address of 0x3FF80000.
+
+//The testament is a FIFO. The ROM will output all data between textstart and textend; if textend is lower than textstart it will
+//output everything from textstart to memend, then memstart to textend.
+typedef struct {
+    char *memstart; //start of memory region
+    char *memend;   //end of memory region
+    char *textstart; //start of text to output
+    char *textend;
+} usbdc_testament_t;
+
+#ifdef __cplusplus
+}
+#endif